【问题标题】:Adobe Air. Strange bug with URLStream or FileStream土坯空气。 URLStream 或 FileStream 的奇怪错误
【发布时间】:2012-03-07 21:38:06
【问题描述】:

我使用了这里的示例 Download a file with Adobe AIR 并构建了从服务器下载文件的应用程序。

我将尝试逐步解释错误。

1) Adob​​e Air 应用程序从服务器 http://example.com/data/init.xml 下载 xml 文件

2) 我已经打开了,一切正常。

3) Adob​​e Air 应用程序再次从服务器下载了相同的文件。现在,如果我用记事本打开它,它会说 init.xml 是二进制文件。如果我从磁盘中删除 init.xml 并重试 - 一样。 init.xml 是一个二进制文件。重新打开空气应用程序不起作用。

4) 我将服务器上的 init.xml 更改为 init123.xml 并再次下载。 init123.xml 作为普通 xml 文件打开。如果我再次下载它,那么第 3 步 - init123.xml 是一个二进制文件。

错误可能在哪里?

谢谢。

操作系统 - Windows 7

文件的 MD5 也发生了变化。

这可以解决,我在 url 的末尾添加随机数。

urlStream.load(new URLRequest(remoteFile+'?'+Math.random()));

但是这个

urlStream.load(new URLRequest(remoteFile));

如果我第二次加载它会使文件二进制。

来源

    private function startDownloading():void
    {
        destFile.nativePath = destDirectory +destFileBase;

        fileStream = new FileStream();            
        fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, outputProgress);
        fileStream.addEventListener(IOErrorEvent.IO_ERROR, fileAccessError);
        fileStream.openAsync(destFile, FileMode.WRITE);

        urlStream = new URLStream();
        urlStream.addEventListener(ProgressEvent.PROGRESS, progress);
        urlStream.addEventListener(Event.COMPLETE, complete);
        urlStream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, urlStreamSecurityError);
        urlStream.addEventListener(IOErrorEvent.IO_ERROR, urlStreamIOError);
        urlStream.load(new URLRequest(remoteFile));
    }

    protected function fileAccessError(event:IOErrorEvent):void
    {
        urlStream.close();
        fileStream.close();

    }

    protected function outputProgress(event:OutputProgressEvent):void
    {
        if(event.bytesPending == 0 && downloadCompleteFlag ) {

        }
    }               

    protected function urlStreamIOError(event:IOErrorEvent):void
    {
        trace('error 2');
    }       

    protected function urlStreamSecurityError(event:SecurityErrorEvent):void
    {
        trace('error 2');
    }

    protected function progress(event:ProgressEvent):void
    {
        var bytes :ByteArray = new ByteArray();
        var thisStart :uint = currentPosition;
        currentPosition += urlStream.bytesAvailable;
        urlStream.readBytes( bytes, thisStart );
        fileStream.writeBytes( bytes, thisStart );

    }       
    protected function complete(event:Event):void
    {
        urlStream.close();
        fileStream.close();
        downloadCompleteFlag = true;
    }

【问题讨论】:

  • 您为什么使用 URLStream 而不是 URLLoader?我不知道 Stream 相关的类,但是 URLLoader 可以让你指定数据格式。
  • 你能提供一些代码吗?您用来保存文件的代码也可能很有用。
  • 您没有报告看到任何 'error 2',所以我想没有。你能追踪 currentPositionurlStream.bytesAvailable 吗?
  • 您确定开始下载时目标文件为空吗?
  • 感谢您的回答。它看起来像带有缓存的东西。因为,有了这个新的 URLRequest(remoteFile+'?'+Math.random()) 可以完美地工作。如果我能解决这个问题,我会尝试在不同的操作系统上进行实验。

标签: actionscript-3 apache-flex air


【解决方案1】:

据我所知,图像正在被缓存,这会导致文件立即加载。
你的代码没有处理这个问题,因为在你的完整函数中你没有做fileStream.writeBytes,这会导致一个空文件。
这不是经过测试的代码,但您需要执行类似的操作。

protected function progress(event:ProgressEvent):void
{
  var bytes :ByteArray = new ByteArray();
  var thisStart :uint = currentPosition;
  currentPosition += urlStream.bytesAvailable;
  urlStream.readBytes(bytes, thisStart );
  if(bytes.length > 0){
    fileStream.writeBytes( bytes, thisStart );
  }
}       
protected function complete(event:Event):void
{
  progress(event);// call progress to verify data is written
  urlStream.close();
  fileStream.close();
  downloadCompleteFlag = true;
}

【讨论】:

    【解决方案2】:

    您在错误的位置读取和写入 ByteArray。你有:

    // In "progress" function
    urlStream.readBytes( bytes, thisStart );
    fileStream.writeBytes( bytes, thisStart );
    

    其中thisStarturlStream 中当前可用的字节数。

    当使用URLStream.readBytes() 时,position 指的是您要开始读入bytes 的位置。同样,FileStream.writeBytes() 中的position 参数指的是您要从bytes 开始读取的位置。由于每次调用progress() 时都会重新实例化bytes,因此您应该始终从0 的位置开始读取和写入。

    【讨论】:

    • 对不起,我必须 -1 这个答案。 thisStart 是他上一次迭代的偏移量。他不想一遍又一遍地重新读取相同的字节。他想从上次停下的地方继续。从字节数组中读取字节不会从该字节数组中删除它们
    • @The_asMan Read the docs: "开始读取数据的偏移量字节。默认为 0"。
    • 第一次迭代是从零开始。第二次迭代他想从第一次迭代停止的地方开始阅读。第三次迭代在第二次停止的地方。随着数据的流式传输,它被添加到 byteArray 中,而不是替换数据。
    • 这是流式传输的好处。您只需要处理到达的新数据。如果他每次都重写文件中的数据,那么按照你的方式做就行得通,这将是多余的和更慢的。
    • (我知道这是旧的,但如果为了任何人的利益遇到这个。)代码的结构方式,偏移量应该0,而不是thisStart。假设thisStart 是 10,000,并且有 1,000 个字节可用。 readBytes 将在 ByteArray 中分配 11,000 个字节并将数据写入最后 1000 个字节,然后读取将读出相同的 1000 个字节。每次使用较大的 thisStart 值调用此函数时,将分配较大的 ByteArray。这是咀嚼大量内存的好方法。 (只是在一些遗留代码中修复了这个问题 ;-)
    【解决方案3】:

    尝试清空目标文件。您可能在 init.xml 中保留了之前的字节。

    【讨论】:

    • 即使我完全删除了 init.xml - 它也会作为二进制数据再次下载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多