2008-12-05 67 views
17

如何在基於Flex的AIR應用程序中從互聯網上下載文件。使用Adobe AIR下載文件

我試過使用url設置爲地址的文件,但是當我試圖保存它時,我得到了一個不存在的文件錯誤。谷歌真的很難在這個問題上尋求幫助。

回答

25

你想從2個api組合中選擇來完成這個任務。

版1是URLLoader和的FileStream

使用類的結合,你會通過URLLoader對象加載從服務器的文件中的空氣。這會將文件下載到內存中,然後在下載完成時通知您。確保使用URLLoaderDataFormat.BINARY的dataFormat啓動下載。然後,您將啓動Filestream對象,並使用writeBytes()將其寫入磁盤。

版本2 URLStream在和的FileStream

URLStream在非常類似的URLLoader,但不是等待文件使用結果之前完全下載,數據在下載時提供給您。這種方法適用於大文件,因爲您不必等待完整下載開始將其保存到磁盤,並且您還可以節省內存,因爲一旦播放器將其釋放給您,它可以釋放與該數據相關的內存。 YOu會以完全相同的方式使用文件流,您只需在文件流入時對文件的每個塊執行writeBytes()。

+1

我想補充一下:1.如果我們用URLStream加載一些文件,並且不用FileStream把它寫入文件 - 應用程序的大小增長到我們加載的文件的大小。但是,如果我們從流中讀取字節並將它們寫入文件 - 一切正常。應用程序不增長。要獲取應用程序大小,請使用System.privateMemory。 – yozhik 2011-11-03 15:28:13

+0

@Seanalltogether,你能舉一個例子但不使用包嗎? – 2012-08-20 02:09:59

0

查看flash.net.URLRequest類,它可以幫助您下​​載文件。

7

要在seanalltogether的第二個想法基礎上構建,下面是一個函數,從互聯網文件,並將其保存到磁盤(在指定的文件名在桌面上):

downloadFile: function (url, fileName) { 
    var urlStream = new air.URLStream(); 
    var request = new air.URLRequest(url); 
    var fileStream = new air.FileStream(); 
    // write 50k from the urlstream to the filestream, unless 
    // the writeAll flag is true, when you write everything in the buffer 
    function writeFile(writeAll) { 
     if (urlStream.bytesAvailable > 51200 || writeAll) { 
      alert("got some"); 
      var dataBuffer = new air.ByteArray(); 
      urlStream.readBytes(dataBuffer, 0, urlStream.bytesAvailable); 
      fileStream.writeBytes(dataBuffer, 0, dataBuffer.length); 
     } 
     // do clean up: 
     if (writeAll) { 
      alert("done"); 
      fileStream.close(); 
      urlStream.close(); 
      // set up the next download 
      setTimeout(this.downloadNextFile.bind(this), 0); 
     } 
    } 

    urlStream.addEventListener(air.Event.COMPLETE, writeFile.bind(this, true)); 
    urlStream.addEventListener(air.ProgressEvent.PROGRESS, writeFile.bind(this, false)); 

    var file = air.File.desktopDirectory.resolvePath(fileName); 
    fileStream.openAsync(file, air.FileMode.WRITE); 

    urlStream.load(request); 

} 

注:該解決方案使用原型的AIRAliases.js和。

14

我用seanalltogether的答案,並寫了這個類來處理文件下載。

這很簡單。創建一個var downloader = new FileDownloader("url", "Local/Path");並致電downloader.load()開始下載。

它還支持設置完成時調用的函數以及下載時的點。傳遞onProgress函數已經下載的字節數。 (我無法弄清楚如何讓一小部分,因爲我無法弄清楚如何查詢文件的大小,它被下載之前)

package com.alex{ 
import flash.filesystem.File; 
import flash.filesystem.FileMode; 
import flash.filesystem.FileStream; 
import flash.net.URLRequest; 
import flash.net.URLStream; 
import flash.utils.ByteArray; 

public class FileDownloader 
{ 

    // Class to download files from the internet 

    // Function called every time data arrives 
    //  called with an argument of how much has been downloaded 
    public var onProgress :Function = function(t:uint):void{}; 
    public var onComplete :Function = function():void{}; 
    public var remotePath :String = ""; 
    public var localFile :File = null; 

    private var stream :URLStream; 
    private var fileAccess :FileStream; 

    public function FileDownloader(remotePath :String = "" , localFile :File = null) { 

     this.remotePath = remotePath; 
     this.localFile = localFile; 
    } 

    public function load() :void { 
     if(!stream || !stream.connected) { 
      stream = new URLStream(); 
      fileAccess = new FileStream(); 

      var requester :URLRequest = new URLRequest(remotePath); 
      var currentPosition :uint = 0; 
      var downloadCompleteFlag :Boolean = false; 

      // Function to call oncomplete, once the download finishes and 
      //  all data has been written to disc    
      fileAccess.addEventListener("outputProgress", function (result) :void { 
       if(result.bytesPending == 0 && downloadCompleteFlag) { 

        stream.close(); 
        fileAccess.close(); 
        onComplete(); 
       } 
      }); 

      fileAccess.openAsync(localFile, FileMode.WRITE); 

      stream.addEventListener("progress" , function() :void { 

       var bytes :ByteArray = new ByteArray(); 
       var thisStart :uint = currentPosition; 
       currentPosition += stream.bytesAvailable; 
       // ^^ Makes sure that asyncronicity does not break anything 

       stream.readBytes(bytes, thisStart); 
       fileAccess.writeBytes(bytes, thisStart); 

       onProgress(currentPosition);      
      }); 

      stream.addEventListener("complete", function() :void { 
       downloadCompleteFlag = true; 
      }); 

      stream.load(requester); 

     } else { 
      // Do something unspeakable 
     } 
    } 
}}