如何在基于Flex的AIR应用程序中从Internet下载文件。
我尝试使用url设置为该地址的文件,但是当我尝试保存时,我得到了一个文件不存在错误。在这个问题上谷歌寻求帮助真的很难。
答案 0 :(得分:25)
你想从2个api组合中做出选择来实现这个目标。
版本1是URLLoader和FileStream
使用此类的组合,您可以通过URLLoader对象将服务器中的文件加载到空中。这会将文件下载到内存中,然后在下载完成时通知您。确保使用URLLoaderDataFormat.BINARY的dataFormat启动下载。然后,您将启动Filestream对象并使用writeBytes()将其写入磁盘。
版本2是URLStream和FileStream
URLStream与URLLoader非常相似,但在使用结果之前,不是等待文件完全下载,而是在下载过程中向您提供数据。这种方法适用于大型文件,因为您不必等待完整下载开始将其保存到磁盘,并且还可以节省内存,因为一旦播放器将其交给您,它就可以释放与该数据相关的内存。你会以完全相同的方式使用文件流,你最终会在文件流入时在文件的每个块上做一个writeBytes()。
答案 1 :(得分: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
}
}
}}
答案 2 :(得分: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);
}
注意:此解决方案使用Prototype和AIRAliases.js。
答案 3 :(得分:0)
查看可帮助您下载文件的flash.net.URLRequest
课程。
答案 4 :(得分:0)
还请检查URLLoader类以下载文件。这里有一个很好的例子:http://www.adobe.com/devnet/air/flex/articles/exploring_file_capabilities.html
与URLStream类相比,这对我来说非常快,这需要花费很多时间,并且需要大量的CPU才能下载文件。