为什么在文件未完成加载时会调度URLStream完成事件?

时间:2013-01-24 03:08:05

标签: actionscript-3 flash air

我正在编写AIR kiosk应用程序,每晚都连接到WordPress服务器,获取带有所有内容路径的JSON文件,然后下载该内容并将其保存到自助服务终端硬盘。

有几百个文件(jpg,png,f4v,xml),大多数文件下载/保存没有问题。但是,有两个永远不会完全下载的f4v文件。完整事件确实会被调度,但如果我比较bytesTotal(来自progress事件)vs bytesAvailable(来自complete事件),它们就不匹配; bytesTotal更大。 bytesTotal(来自progress事件)匹配服务器上的字节。

progress事件中的bytesLoaded永远不会增加到与bytesTotal匹配的点,因此我也不能依赖progress事件。这似乎每次都发生在相同的两个视频上。视频不是很大,一个是13MB,另一个是46MB。我有更大的视频下载没有任何问题。

编辑:重新启动计算机后,这两个视频现已完成下载,但我遇到了300kb png文件的相同问题。

如果我将网址粘贴到Firefox中,则会正确下载。我还编写了一个简单的c#app来下载文件,它可以毫无问题地下载它们,所以它似乎是Flash / AIR的一个问题。

编辑:这是一个更简单的代码版本,这是来自一个测试项目,它是唯一的代码(网址在我们的本地网络上,所以你不能自己下载文件):

package  {

    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.net.URLRequest;
    import flash.net.URLStream;

    [SWF(backgroundColor="#000000", frameRate="24", width="640", height="480")]

    public class Test extends Sprite {

        private var fileSize:Number;
        private var stream : URLStream;
        private var url:String = "http://192.168.150.219/wordpress2/wp-content/uploads/2012/12/John-Butler-clip1.f4v";

        public function Test() {
            if (stage)
                init();
            else
                this.addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event=null):void {
            this.removeEventListener(Event.ADDED_TO_STAGE, init);
            stream = new URLStream();
            stream.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);
            stream.addEventListener(Event.COMPLETE, onLoadComplete);
            stream.load(new URLRequest(url));
        }

        private function onLoadProgress(event:ProgressEvent):void {
            fileSize = event.bytesTotal;
            var percent:Number = event.bytesLoaded / event.bytesTotal * 100;
            trace(percent + "%"); // this never gets to 100%
        }

        private function onLoadComplete(event:Event):void {
            trace("loaded", stream.bytesAvailable, "of", fileSize); 
            // outputs "loaded 13182905 of 13184365"
            // so why is it "complete" when it isn't fully downloaded?
        }
    }
}

3 个答案:

答案 0 :(得分:2)

请勿与bytesAvailable进行比较,请改用length。 BytesAvailable实际上是ByteArray.length - ByteArray.position。因此,如果ByteArray中的位置已从索引0移开,则bytesAvailable值将减小。长度始终是数组中的总字节数。

尝试比较使用长度,看看这是否有所不同。我没有时间筛选你的代码,看看你是否在任何时候改变位置(有意或无意地;你可以用多种方式做到这一点),所以这是我现在能提供的最好的。

答案 1 :(得分:2)

如果其他人像我一样有同样的问题。事实证明,AIR中存在一个缓存问题,因此添加到请求中的时间戳解决了这个问题:http://www.newtonflash.com/blog/as3/prevent-xml-caching-problem/#comment-43

{
var xmlPath:String="replaceYourXMLPathHere.xml"
var urlReq:URLRequest = new URLRequest(xmlPath+"?time=" + new Date().getTime());
}

答案 2 :(得分:0)

你的答案就在你的问题中。

普通网址(文件) - 对于此服务器,这是一个数据块。服务器提供“数据块”后,交付流程将被视为“完整”。在这种情况下,如果文件是100kb,一旦收到100kb - Flash将其视为“完成”。

URLStream - 对于服务器,这是[ TWO ]数据块(非常简单的查看方式)。服务器将首先将 CONNECTION 提供给流...然后提供 STREAM DATA 。这与Flash中描述的一样在Flash中处理。

Flash会将 CONNECTION 加载为“完整”,从不检查 STREAM 数据已加载 - 这取决于您的服务器。在任何流中,您应该实际检查[load progress]事件并读取数据的每个字节,然后根据需要进行构造。