如何在基于Flex的AIR应用程序中从Internet下载文件.
我尝试使用url设置为该地址的文件,但是当我尝试保存它时,我得到了一个文件不存在错误.谷歌在这个问题上寻求帮助真的很难.
你想从2个api组合中做出选择来实现这个目标.
版本1是URLLoader和FileStream
使用此类的组合,您可以通过URLLoader对象将服务器中的文件加载到空中.这会将文件下载到内存中,然后在下载完成时通知您.确保使用URLLoaderDataFormat.BINARY的dataFormat启动下载.然后,您将启动Filestream对象并使用writeBytes()将其写入磁盘.
版本2是URLStream和FileStream
URLStream与URLLoader非常相似,但在使用结果之前,不是等待文件完全下载,而是在下载期间向您提供数据.这种方法适用于大型文件,因为您不必等待完整下载开始将其保存到磁盘,并且还可以节省内存,因为一旦播放器将其交给您,它就可以释放与该数据相关的内存.你会以完全相同的方式使用文件流,你最终会在文件流入时在文件的每个块上执行writeBytes().
我使用了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 } } }}
为了建立seanalltogether的第二个想法,这里有一个函数应该从Internet下载文件,并将其保存到磁盘(在桌面上的指定文件名中):
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); }
注意:此解决方案使用Prototype和AIRAliases.js.