[ActionScript 3.0] File下載工具

更新數據原理,訪問接口,將服務器數據抓取並下載到本地的臨時文件夾,當全部下載完成,卸載客戶端內容,出現升級界面,此時移動下載的內容到目標文件夾,移動完成再從新加載客戶端,訪問接口,下載文件,移動文件均是隊列完成。json

根據實際接口操做可替換源代碼中的必要代碼,如下是源碼:數組

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+"--\n");
                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+"個-----\n");
                        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+"個資源下載完成\n");
                _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("------>>全部資源移動完成--------\n");
            
            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.asapp

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("\n<<----------------- aticon: "+_connectionURL+" ----------------- argument: "+_argument+" -------------------------->>\nresult: \n"+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 ide

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+"\n");
                }    
            }
        }
        /**
         * 開始移動文件
         * @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()
        {
        }
    }
}

若要爲己所用,據具體需求請改代碼。ui

相關文章
相關標籤/搜索