Actionscript 3 AdobeAIR。URLStream或FileStream的奇怪错误

Actionscript 3 AdobeAIR。URLStream或FileStream的奇怪错误,actionscript-3,apache-flex,air,Actionscript 3,Apache Flex,Air,我使用了这里的示例,并构建了从服务器下载文件的应用程序 我将尝试按步骤解释错误 1) AdobeAIR应用程序从服务器下载了xml文件 2) 我已经打开了,一切正常 3) AdobeAIR应用程序再次从服务器下载了相同的文件。现在,如果我用记事本打开它,它会说init.xml是二进制文件。如果我从磁盘中删除init.xml并重试-相同。init.xml是一个二进制文件。重新打开air应用程序不起作用 4) 我将服务器上的init.xml改为init123.xml,然后再次下载。init123.x

我使用了这里的示例,并构建了从服务器下载文件的应用程序

我将尝试按步骤解释错误

1) AdobeAIR应用程序从服务器下载了xml文件

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

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

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

错误在哪里

多谢各位

操作系统-Windows7

文件的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;
    }

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

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

您在字节数组中的读写位置错误。你有:

// In "progress" function
urlStream.readBytes( bytes, thisStart );
fileStream.writeBytes( bytes, thisStart );
其中,
thisStart
urlStream
中可用的当前字节数


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

的位置开始读写,因为您的字节数组位于错误的位置。你有:

// In "progress" function
urlStream.readBytes( bytes, thisStart );
fileStream.writeBytes( bytes, thisStart );
其中,
thisStart
urlStream
中可用的当前字节数


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

的位置开始读写,从我可以看出图像正在缓存,这将导致文件的即时加载。
您的代码没有处理这个问题,因为在您的完整函数中,您没有执行将成为空文件的
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;
}

据我所知,图像正在被缓存,这将导致文件的即时加载。
您的代码没有处理这个问题,因为在您的完整函数中,您没有执行将成为空文件的
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;
}


您为什么使用URLStream而不是URLLoader?我不知道与流相关的类,但URLLoader允许您指定数据格式。您能提供一些代码吗?你用来保存文件的代码可能也很有用。你没有报告看到任何“错误2”,所以我想没有。能否跟踪currentPosition和urlStream.bytesAvailable?开始下载时是否确定目标文件为空?谢谢您的回答。它看起来像是有缓存的东西。因为,使用这个新的URLRequest(remoteFile+'?'+Math.random())可以完美地工作。我会尝试在不同的操作系统上进行实验,如果我能解决这个问题,我会写一篇文章。你为什么使用URLStream而不是URLLoader?我不知道与流相关的类,但URLLoader允许您指定数据格式。您能提供一些代码吗?你用来保存文件的代码可能也很有用。你没有报告看到任何“错误2”,所以我想没有。能否跟踪currentPosition和urlStream.bytesAvailable?开始下载时是否确定目标文件为空?谢谢您的回答。它看起来像是有缓存的东西。因为,使用这个新的URLRequest(remoteFile+'?'+Math.random())可以完美地工作。我将尝试在不同的操作系统上进行实验,并写下我是否能够解决这个问题。即使我完全删除init.xml,它也将作为二进制数据再次下载。即使我完全删除init.xml,它也将作为二进制数据再次下载。抱歉,我必须-1这个答案。thisStart是他上次迭代的偏移量。他不想一次又一次地重读相同的字节。他想从上次停下来的地方重新开始。从字节数组中读取字节并不会从该数组中删除它们bytearray@The_asMan:“开始读取数据的字节偏移量。默认值为0”。对于第一次迭代,是从0开始。第二次迭代他想从第一次迭代结束的地方开始阅读。第三次迭代,第二次停止。当数据以流方式传输时,它被添加到byteArray中,而不是替换数据。这就是流式传输的好处。您只需要处理到达的新数据。如果他每次都重写文件中的数据,那么按照你的方式来做就行了,这将是多余的,而且速度会慢一些。(我知道这是旧的,但这是为了方便任何人看到它。)按照代码的结构,偏移量应该是
0
,而不是
thisStart
。让我们假设
这个start
是10000,有1000个字节可用。readBytes将在ByteArray中分配11000个字节,并将数据写入最后1000个字节,然后read将读取相同的1000个字节。每次调用this时,都会为
thisStart
分配一个较大的ByteArray值。这是一个很好的方式来咀嚼大量的记忆。(刚刚在一些遗留代码中修复了这个问题;-)对不起,我必须-1这个答案。thisStart是他上次迭代的偏移量。他不想