[ActionScript 3.0] File下载工具

更新数据原理,访问接口,将服务器数据抓取并下载到本地的临时文件夹,当所有下载完成,卸载客户端内容,出现升级界面,此时移动下载的内容到目标文件夹,移动完成再重新加载客户端,访问接口,下载文件,移动文件均是队列完成。

根据实际接口操作可替换源代码中的必要代码,以下是源码:

DownloadControl.as

package com.controls
{
    import com.controls.download.ConnectionUtil;
    import com.controls.download.DownloadFile;
    import com.controls.download.FileManager;
    import com.models.Config;
    import com.models.events.AppEvent;
    import com.models.events.AppEventDispatcher;
    
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.URLVariables;
    import flash.utils.ByteArray;

    /**
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2017-2-20 下午4:19:33
     *
     */
    public class DownloadControl
    {
        /**
         * 下载资源的计数器
         */
        private var _count:uint;
        /**
         * 第一级接口个数计数器
         */
        private var _firstCount:int;
        /**
         * 第二级接口个数计数器
         */
        private var _secondCount:int;
        /**
         * 第一级接口返回的数据,供第二级接口递归调用
         */
        private var _datas:Object;
        
        private static var _instance:DownloadControl;
        public function DownloadControl(s:S)
        {
        }
        public static function getInstance():DownloadControl
        {
            if(!_instance){
                _instance = new DownloadControl(new S());
            }
            return _instance;
        }
        public function reset():void
        {
            _count = 0;
            _firstCount = 0;
            _secondCount = 0;
            _datas = null;
            Config.downloadData = [];
        }
        /**
         * 一级接口请求
         */
        public function connection1():void
        {
            var connection:ConnectionUtil = new ConnectionUtil();
            connection.connect(Config.connection+Config.config.link.item[_firstCount].@typeLink,Config.config.link.item[_firstCount].@name+".json","",null,onConnectComplete);
        }
        /**
         * 二级接口请求
         */
        private function connection2(datas:Object):void
        {
            var total:int = datas["data"]["response"].length;
            var variables:URLVariables = new URLVariables();
            variables.parameter = datas["data"]["response"][_secondCount]["id"];
            var connection:ConnectionUtil = new ConnectionUtil();
            connection.connect(Config.connection+Config.config.link.item[_firstCount].@contentLink,Config.config.link.item[_firstCount]+"_"+_secondCount+".json","",variables,onConnectComplete1);
            
            function onConnectComplete1(data:Object):void
            {
                
                for(var i:int = 0;i<data["data"]["response"].length;i++){
                    if(data["data"]["response"][i]["videoUrl"]){
                        var label:String = "videoUrl";
                    }
                    if(data["data"]["response"][i]["imgUrl"]){
                        label = "imgUrl";
                    }
                    var len:int = data["data"]["response"][i][label].length;
                    for(var j:int = 0;j<len;j++){//存储下载的文件名称
                        Config.downloadData.push(data["data"]["response"][i][label][j]["openFile"]);
                        if(label == "videoUrl"){
                            Config.downloadData.push(data["data"]["response"][i][label][j]["vframe"]);
                        }
                    }
                    
                }
                Config.jsonArr[_firstCount][_secondCount]["second"] = data["data"]["response"];//二级菜单保存
                _secondCount++;
                trace("------>>"+_secondCount+"------"+total+"--
");
                if(_secondCount >= total){
                    _firstCount++;
                    if(_firstCount>Config.config.link.item.length()-1){
                        //所有接口请求完成,将json保存到本地
                        var file:File = new File(Config.jsonPath+"data.json");
                        var fs:FileStream = new FileStream();
                        fs.open(file,FileMode.WRITE);
                        fs.writeBytes(getByteArr(JSON.stringify(Config.jsonArr)));
                        fs.close();
                        file = null;
                        fs = null;
                        //所有接口请求完成,开始下载
                        trace("------>>所有接口请求完成,开始下载---资源共:"+Config.downloadData.length+"个-----
");
                        startDownload();
                    }else{
                        connection1();
                    }
                    
                }else{
                    connection2(_datas);
                }
            }
        }
        private function onConnectComplete(data:Object):void
        {
            
            trace(JSON.stringify(data));
            _datas = data;
            _secondCount=0;
            Config.jsonArr[_firstCount] = data["data"]["response"];//一级菜单保存
            connection2(data);
        }
        /**
         * 开始下载
         * @param isAll true表示所有资源同时下载 false表示资源队列下载
         */
        private function startDownload(isAll:Boolean=true):void
        {
            if(isAll){
                for(var i:int = 0;i<Config.downloadData.length;i++){
                    download(i);
                }
            }else{
                download(_count);
            }
            
            function download(i:int):void
            {
                new DownloadFile().download(Config.source,Config.downloadData[i],Config.tempPath,Config.assets,onDownloaded);
            }
            function onDownloaded():void
            {
                trace("------>>第"+_count+"个资源下载完成
");
                _count++;
                if(_count == Config.downloadData.length){//Config.downloadData.length
                    trace("------>>所有资源下载完成--------");
                    var tempList:Array = new File(Config.tempPath).getDirectoryListing();
                    AppEventDispatcher.getInstance().dispatchEvent(new AppEvent(AppEvent.DOWNLOAD_COMPLETE,tempList.length));
                    
                }else{
                    if(!isAll){
                        download(_count);
                    }
                }
            }
        }
        public function startMove():void
        {
            FileManager.deleteFilesByNotSame(Config.downloadData,Config.assets);
            FileManager.startMoveFiles(File.applicationDirectory.nativePath+"/source/",Config.assets,onMoveComplete);
        }
        private function onMoveComplete():void
        {
            trace("------>>所有资源移动完成--------
");
            
            AppEventDispatcher.getInstance().dispatchEvent(new AppEvent(AppEvent.UPDATE_COMPLETE));
        }
        /**
         * 将String转换成ByteArray类型
         * @param param  被转换的String
         * @return ByteArray  转换后的ByteArray
         * 
         */    
        private function getByteArr(param:String):ByteArray
        {
            var bytes:ByteArray = new ByteArray;
            bytes.writeUTFBytes(param);
            return bytes;
        }
    }
}
class S{
    
}

接口连接工具类 ConnectionUtil.as

package com.controls.download
{
    
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;
    import flash.utils.ByteArray;

    /**
     * 连接接口工具类
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2017-2-16 下午2:50:58
     *
     */
    public class ConnectionUtil extends EventDispatcher
    {
        private var _ldr:URLLoader;
        /**
         * 将返回数据写入到本地,此为本地存储路径
         */
        private var _localPath:String;
        /**
         * 将返回数据写入到本地,此为文件名称
         */
        private var _fileName:String;
        /**
         * 接口连接地址
         */
        private var _connectionURL:String;
        /**
         * 接口所需参数
         */
        private var _argument:String;
        /**
         * 从接口获取的数据
         */
        public var data:Object;
        /**
         * 接口连接成功,获取数据后回调函数
         */
        public var onConnectSucceed:Function=null;
        public function ConnectionUtil()
        {
            _ldr = new URLLoader();
            _ldr.addEventListener(Event.COMPLETE,onConnectComplete);
            _ldr.addEventListener(IOErrorEvent.IO_ERROR,onError);
        }
        
        /**
         * 连接接口成功
         */
        private function onConnectComplete(e:Event):void
        {
            var str:String = e.target.data;
            data = JSON.parse(str);
            
            trace("
<<----------------- aticon: "+_connectionURL+" ----------------- argument: "+_argument+" -------------------------->>
result: 
"+str);
            if(data.code == "200"){
                
                //将json写入本地
                /*var file:File = new File(_localPath+_fileName);
                var fs:FileStream = new FileStream();
                fs.open(file,FileMode.WRITE);
                fs.writeBytes(getByteArr(str));
                fs.close();
                file = null;
                fs = null;*/
                if(onConnectSucceed!=null) onConnectSucceed(data);
            }
            
        }
        private function onError(e:IOErrorEvent):void
        {
            trace("error:"+e.text);
        }
        
        
        /**
         * 访问接口,获取数据
         * @param connectPath:接口地址
         * @param path : 将接口返回的json写入本地,此为本地地址
         */
        public function connect(connectPath:String,fileName:String,localPath:String="",argument:URLVariables=null,callback:Function=null,who:String=""):void
        {
            _connectionURL = connectPath;
            
            _fileName = fileName;
            localPath ==""?_localPath = File.applicationDirectory.nativePath+"/json/": _localPath = localPath;
            trace("接口地址:"+connectPath);
            var request:URLRequest = new URLRequest(connectPath);
            request.method = URLRequestMethod.POST;
            if(argument){
                request.data = argument;
                _argument = argument.parameter;
            }else{
                _argument = "无参数";
            }
            _ldr.load(request);
            
            if(callback!=null) onConnectSucceed = callback;
        }
        /**
         * 将String转换成ByteArray类型
         * @param param  被转换的String
         * @return ByteArray  转换后的ByteArray
         * 
         */    
        private function getByteArr(param:String):ByteArray
        {
            var bytes:ByteArray = new ByteArray;
            bytes.writeUTFBytes(param);
            return bytes;
        }
    }
}

下载文件类 DownloadFile.as

package com.controls.download
{
    import com.models.Config;
    
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.net.URLRequestHeader;
    import flash.utils.ByteArray;

    /**
     * 下载文件工具类
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2017-2-16 下午12:55:22
     *
     */
    public class DownloadFile extends EventDispatcher
    {
        private var _downloadLoader:URLLoader;
        /**
         * 是否下载完成标识
         */
        private var _downloadEnd:Boolean;
        private var _startPoint:uint = 0;
        private var _endPoint:uint = 0;
        private var _total:uint = 0;
        /**
         * 文件名(xx.jpg,xx.flv)
         */
        private var _fileName:String;
        /**
         * 下载时保存的临时路径,下载完成后需要从这个地址移动到程序访问的路径
         */
        private var _tempPath:String = ""; 
        /**
         * 程序访问资源的本地路径
         */
        private var _localPath:String = "";
        /**
         * 服务端抓取数据的路径
         */
        private var _remotePath:String = "";
        /**
         * 下载完成回调函数
         */
        private var _downloadComplete:Function;
        
        public function DownloadFile()
        {
            init();
        }
        private function init():void
        {
            _downloadLoader = new URLLoader();
            _downloadLoader.dataFormat = URLLoaderDataFormat.BINARY;
            _downloadLoader.addEventListener(Event.COMPLETE,onLoaded);
            _downloadLoader.addEventListener(IOErrorEvent.IO_ERROR,onError);
        }
        private function onLoaded(e:Event):void
        {
            if(e.target.data.length == 0){
                writeBytes(_tempPath,e.target.data,0,e.target.data.length);
                this.dispatchEvent(new Event(Event.COMPLETE));
                if(_downloadComplete!=null) _downloadComplete();
            }else{
                if(_downloadEnd){
                    _startPoint = _endPoint;
                    writeBytes(_tempPath,e.target.data,0,e.target.data.length);
                    this.dispatchEvent(new Event(Event.COMPLETE));
                    if(_downloadComplete!=null) _downloadComplete();
                }else{
                    _startPoint = _endPoint;
                    writeBytes(_tempPath,e.target.data,0,e.target.data.length-1);
                    stepDownload();
                }
            }
        }
        /**
         * 将数据写入到本地,即下载
         * @param path  本地保存地址
         * @param bytes 要写入的字节数组。
         * @param offset 从零开始的索引,指定在数组中开始写入的位置。
         * @paramlength 一个无符号整数,指定在缓冲区中的写入范围。
         */
        private function writeBytes(path:String,bytes:ByteArray, offset:uint=0, length:uint=0):void
        {
            var file:File = new File(path+_fileName);
            var fs:FileStream = new FileStream();;
            fs.open(file,FileMode.UPDATE);
            fs.position = fs.bytesAvailable;//将指针指向文件尾
            fs.writeBytes(bytes,offset,length);//在文件中写入新下载的数据
            fs.close();
        } 
        /**
         * 分步下载
         */
        private function stepDownload():void
        {
            _endPoint += 10000000;
            if(_endPoint > _total ){
                _endPoint = _total;
                _downloadEnd = true;
            }
            var request:URLRequest = new URLRequest(_remotePath+_fileName);
            var header:URLRequestHeader = new URLRequestHeader("Range","bytes="+_startPoint+"-"+_endPoint);
            request.requestHeaders.push(header);
            _downloadLoader.load(request);
        }
        /**
         * 开始下载文件
         * @param remoteURL 数据存放的远程地址
         * @param fileName 下载的文件名
         * @param tempPath 下载保存到本地的临时目录
         * @param localPath 最终程序访问的本地目录
         */
        public function download(remotePath:String,fileName:String,tempPath:String,localPath:String,callback:Function=null):void
        {
            _remotePath = remotePath;
            _fileName = fileName;
            _tempPath = tempPath;
            _localPath = localPath;
            
            _downloadComplete = callback;
            _downloadEnd = false;
            _startPoint = 0;
            _endPoint = 0;
            var file:File = new File(_localPath+_fileName);
            if(file.exists){//假如存在此文件,就不下载,跳过
                this.dispatchEvent(new Event(Event.COMPLETE));//可以回调,可以派发
                if(_downloadComplete!=null) _downloadComplete();
            }else{
                _downloadLoader.addEventListener(ProgressEvent.PROGRESS,onProgress);
                _downloadLoader.addEventListener(IOErrorEvent.IO_ERROR,onError);
                try
                {
                    _downloadLoader.load(new URLRequest(_remotePath+_fileName));
                } 
                catch(error:Error) 
                {
                    trace(error.message);
                }
            }
        }
        private function onProgress(e:ProgressEvent):void
        {
            _total = _downloadLoader.bytesTotal;
            _downloadLoader.removeEventListener(ProgressEvent.PROGRESS,onProgress);
            _downloadLoader.close();
            stepDownload();
        }
        private function onError(e:IOErrorEvent):void
        {
            trace(e.text);
            //错误时跳过,继续下一个下载
            if(_downloadComplete!=null) _downloadComplete();
        }
        /**
         * 释放下载工具
         */
        public function dispose():void
        {
            _downloadLoader.removeEventListener(Event.COMPLETE,onLoaded);
            _downloadLoader.removeEventListener(IOErrorEvent.IO_ERROR,onError);
            _downloadLoader.removeEventListener(ProgressEvent.PROGRESS,onProgress);
            _downloadLoader.close();
            _downloadLoader = null;
        }
    }
    
}

文件操作类 FileManager.as

package com.controls.download
{
    
    import flash.events.Event;
    import flash.filesystem.File;

    /**
     * 文件操作类
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2017-2-20 上午11:34:16
     *
     */
    public class FileManager
    {
        private static var _moveCount:int;
        private static var _moveComplete:Function;
        private static var _targetDir:String;
        private static var _tempDir:String;
        private static var _templist:Array;
        
        public function FileManager()
        {
        }
        public static function reset():void
        {
            _moveCount = 0;
            _templist = null;
        }
        /**
         * 在目标目录下删除数组中不存在的文件
         * @param filesName  文件名数组
         * @param targetDir 目标文件夹
         */
        public static function deleteFilesByNotSame(filesName:Array,targetDir:String):void
        {
            var targetList:Array = new File(targetDir).getDirectoryListing();
            for(var i:int;i<targetList.length;i++){
                if(filesName.indexOf(targetList[i].name)==-1){
                    (targetList[i] as File).deleteFile();
                    trace("删除文件:"+(targetList[i] as File).nativePath+"
");
                }    
            }
        }
        /**
         * 开始移动文件
         * @param tempDir 存储下载文件的临时目录
         * @param targetDir 需要移动到的目标目录
         * @callba 移动完成,回调函数
         */
        public static function startMoveFiles(tempDir:String,targetDir:String,callback:Function):void
        {
            _moveCount = 0;
            _targetDir = targetDir;
            _tempDir = tempDir;
            _moveComplete = callback;
            _templist = new File(_tempDir).getDirectoryListing();
            if(_templist.length){
                moveFiles();
            }else{
                _moveComplete();
            }
            
        }
        /**
         * 移动文件
         */
        private static function moveFiles():void
        {
            var fromFile:File = new File(_tempDir+_templist[_moveCount].name);
            var toFile:File = new File(_targetDir+_templist[_moveCount].name);
            trace("移动文件:"+_moveCount+"个-->>"+_templist[_moveCount].name);
            trace(_tempDir+_templist[_moveCount].name,_targetDir+_templist[_moveCount].name);
            fromFile.moveToAsync(toFile,true);
            fromFile.addEventListener(Event.COMPLETE,onFileMoveComplete);
        }
        
        private static function onFileMoveComplete(e:Event):void
        {
            
            _moveCount++;
            if(_moveCount>_templist.length-1){
                //全部移动完成
                _moveComplete();
            }else{
                moveFiles();
            }
            
        }
    }
}

还有个数据存储类 Config.as

package com.models
{
    import flash.filesystem.File;

    /**
     * 
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2017-2-16 下午1:35:43
     *
     */
    public class Config
    {
        public static var config:XML;
        /**
         * 服务器连接地址
         */
        public static var connection:String;
        /**
         * 远程资源地址 cdn
         */
        public static var source:String;
        /**
         * 本地资源地址
         */
        public static var assets:String;
        /**
         * 存储所有下载资源的信息(目前仅存文件名称)
         */
        public static var downloadData:Array = [];
        /**
         * 写入到本地的json目录地址
         */
        public static var jsonPath:String = File.applicationDirectory.nativePath+"/data/";
        /**
         * 下载资源的临时存放目录
         */
        public static var tempPath:String = File.applicationDirectory.nativePath+"/source/";
        /**
         * 接口返回的json数据组合
         */
        public static var jsonArr:Array = [];
        public function Config()
        {
        }
    }
}

若要为己所用,据具体需求请改代码。

原文地址:https://www.cnblogs.com/frost-yen/p/6433037.html