AIR AS3 文件下载在带宽较低时损坏
AIR AS3 file download is corrupted when bandwidth is low
我正在使用下载器 class 从 WS2012 上的 IIS 服务器获取大文件并处理下载进度。
它工作正常,但是当客户端的带宽太饱和时,不再触发 Progress 事件并且在一定时间后下载停止(似乎触发了 Complete 事件?),尽管下载未完成,给客户留下损坏的文件。
我找不到如何解决这个问题,甚至不知道我应该采取什么策略来解决这个问题(完成下载并显示错误?等待带宽可用性来获取我的下一个字节?)
这是Downloader.asclass
public class Downloader extends EventDispatcher
{
[Event(name="DownloadComplete", type="DownloadEvent")]
public static var spd:int = 0;
private var file:File;
private var fileStream:FileStream;
private var url:String;
private var urlStream:URLStream;
var mc_background:MovieClip;
var howManyTimes:Number = 3; //How many times per second the download speed will be traced
var bytesLoaded:Number = 0; //don't change, necessary for calculation
var lastTime:int = 0; //don't change, necessary for calculation
private var waitingForDataToWrite:Boolean = false;
public function Downloader(s:MovieClip)
{
mc_background = s;
lastTime = getTimer();
urlStream = new URLStream();
urlStream.addEventListener(Event.OPEN, onOpenEvent);
urlStream.addEventListener(ProgressEvent.PROGRESS, onProgressEvent);
urlStream.addEventListener(Event.COMPLETE, onCompleteEvent);
fileStream = new FileStream();
fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler)
}
public function download(formUrl:String, toFile:File):void {
this.url = formUrl;
this.file = toFile;
mc_background.pb.file_txt.text = file.name;
fileStream.openAsync(file, FileMode.WRITE);
urlStream.load(new URLRequest(url));
}
private function onOpenEvent(event:Event):void {
waitingForDataToWrite = true;
dispatchEvent(event.clone());
}
private function onProgressEvent(event:ProgressEvent):void {
var time:int = getTimer();
if(time - lastTime >= (1000/howManyTimes))
{
var kiloBytes:Number = (event.bytesLoaded - bytesLoaded)/1000;
var timeInSecs:Number = (time - lastTime)/1000;
var kbsPerSecVal:Number = Math.floor(kiloBytes/timeInSecs);
trace(kbsPerSecVal + " kbs/s");
mc_background.pb.speed_txt.text = kbsPerSecVal + " kbs/s";
bytesLoaded = event.bytesLoaded;
lastTime = getTimer();
}
if(waitingForDataToWrite){
writeToDisk();
dispatchEvent(event.clone());
}
}
private function writeToDisk():void {
var fileData:ByteArray = new ByteArray();
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
fileStream.writeBytes(fileData,0,fileData.length);
waitingForDataToWrite = false;
dispatchEvent(new DataEvent(DataEvent.DATA));
}
private function writeProgressHandler(evt:OutputProgressEvent):void{
waitingForDataToWrite = true;
}
private function onCompleteEvent(event:Event):void {
if(urlStream.bytesAvailable>0)
writeToDisk();
fileStream.close();
fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler);
dispatchEvent(event.clone());
// dispatch additional DownloadEvent
dispatchEvent(new DownloadEvent(DownloadEvent.DOWNLOAD_COMPLETE, url, file));
}
}
尝试存储预期文件大小的 int 变量..
当 Event Complete 触发时,现在检查您的 [download] fileData.length 是否等于 expected_FileSize。
如果小于则重试直到等于或任何足够好。要从最后的字节数中获取,您可以在请求 header 中使用 "range request"。 link 如果对您有帮助,它也会显示在此处。
有点像
URLRequestHeader("range","bytes="+startPOS+"-"+endPOS);
其中 startPOS 为 filedata.length+1,endPos 为 expected_FileSize 金额。
我正在使用下载器 class 从 WS2012 上的 IIS 服务器获取大文件并处理下载进度。
它工作正常,但是当客户端的带宽太饱和时,不再触发 Progress 事件并且在一定时间后下载停止(似乎触发了 Complete 事件?),尽管下载未完成,给客户留下损坏的文件。
我找不到如何解决这个问题,甚至不知道我应该采取什么策略来解决这个问题(完成下载并显示错误?等待带宽可用性来获取我的下一个字节?)
这是Downloader.asclass
public class Downloader extends EventDispatcher
{
[Event(name="DownloadComplete", type="DownloadEvent")]
public static var spd:int = 0;
private var file:File;
private var fileStream:FileStream;
private var url:String;
private var urlStream:URLStream;
var mc_background:MovieClip;
var howManyTimes:Number = 3; //How many times per second the download speed will be traced
var bytesLoaded:Number = 0; //don't change, necessary for calculation
var lastTime:int = 0; //don't change, necessary for calculation
private var waitingForDataToWrite:Boolean = false;
public function Downloader(s:MovieClip)
{
mc_background = s;
lastTime = getTimer();
urlStream = new URLStream();
urlStream.addEventListener(Event.OPEN, onOpenEvent);
urlStream.addEventListener(ProgressEvent.PROGRESS, onProgressEvent);
urlStream.addEventListener(Event.COMPLETE, onCompleteEvent);
fileStream = new FileStream();
fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler)
}
public function download(formUrl:String, toFile:File):void {
this.url = formUrl;
this.file = toFile;
mc_background.pb.file_txt.text = file.name;
fileStream.openAsync(file, FileMode.WRITE);
urlStream.load(new URLRequest(url));
}
private function onOpenEvent(event:Event):void {
waitingForDataToWrite = true;
dispatchEvent(event.clone());
}
private function onProgressEvent(event:ProgressEvent):void {
var time:int = getTimer();
if(time - lastTime >= (1000/howManyTimes))
{
var kiloBytes:Number = (event.bytesLoaded - bytesLoaded)/1000;
var timeInSecs:Number = (time - lastTime)/1000;
var kbsPerSecVal:Number = Math.floor(kiloBytes/timeInSecs);
trace(kbsPerSecVal + " kbs/s");
mc_background.pb.speed_txt.text = kbsPerSecVal + " kbs/s";
bytesLoaded = event.bytesLoaded;
lastTime = getTimer();
}
if(waitingForDataToWrite){
writeToDisk();
dispatchEvent(event.clone());
}
}
private function writeToDisk():void {
var fileData:ByteArray = new ByteArray();
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
fileStream.writeBytes(fileData,0,fileData.length);
waitingForDataToWrite = false;
dispatchEvent(new DataEvent(DataEvent.DATA));
}
private function writeProgressHandler(evt:OutputProgressEvent):void{
waitingForDataToWrite = true;
}
private function onCompleteEvent(event:Event):void {
if(urlStream.bytesAvailable>0)
writeToDisk();
fileStream.close();
fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler);
dispatchEvent(event.clone());
// dispatch additional DownloadEvent
dispatchEvent(new DownloadEvent(DownloadEvent.DOWNLOAD_COMPLETE, url, file));
}
}
尝试存储预期文件大小的 int 变量..
当 Event Complete 触发时,现在检查您的 [download] fileData.length 是否等于 expected_FileSize。
如果小于则重试直到等于或任何足够好。要从最后的字节数中获取,您可以在请求 header 中使用 "range request"。 link 如果对您有帮助,它也会显示在此处。
有点像
URLRequestHeader("range","bytes="+startPOS+"-"+endPOS);
其中 startPOS 为 filedata.length+1,endPos 为 expected_FileSize 金额。