1

I've used examples from here Download a file with Adobe AIR and built app that downloads files from server.

I'll try to explain error by steps.

1) Adobe Air app downloaded xml file from server http://example.com/data/init.xml

2) I've opened it and all ok.

3) Adobe Air app again downloaded the same file from server. Now, if I open it with Notepad it says that init.xml is binary file. If I remove init.xml from disk and try again - the same. init.xml is a binary file. Reopen air app doesn't work.

4) I changed init.xml on server to init123.xml and downloaded it again. init123.xml was opened as normal xml file. If I again download it, then step 3 - init123.xml is a binary file.

Where could be the error?

Thank you.

OS - Windows 7

MD5 of files also changed.

This could be solved it I add random number to the end of url.

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

but this

urlStream.load(new URLRequest(remoteFile));

makes file binary if I load it second time.

Source

    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;
    }
Community
  • 1
  • 1
Tuco Ramirez
  • 77
  • 2
  • 7
  • Any reason why you use a URLStream instead of an URLLoader? I don't know about Stream related classes but URLLoader lets you specify data format. – Exort Feb 16 '12 at 13:37
  • Can you provide some code? The code you use to save the file may be useful too. – sch Feb 16 '12 at 13:47
  • You are not reporting seeing any **'error 2'**, so I guess there aren't any. Can you trace **currentPosition** and **urlStream.bytesAvailable**? – sch Feb 16 '12 at 14:09
  • Are you sure the destination file is empty when you start downloading? – sch Feb 16 '12 at 14:17
  • Thank you for answers. It looks like something with cache. Because, with this new URLRequest(remoteFile+'?'+Math.random()) works perfectly. I'll try to experiment on different os and write if i could figure out that problem. – Tuco Ramirez Feb 16 '12 at 14:30

3 Answers3

1

Try emptying the destination file. You are probably keeping the previous bytes in init.xml.

sch
  • 27,436
  • 3
  • 68
  • 83
0

You are reading into and writing from your ByteArray in the wrong position. You have:

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

where thisStart is the current number of bytes available in urlStream.

When using URLStream.readBytes() position refers to the position you want to start reading into bytes. Likewise, the position parameter in FileStream.writeBytes() refers to the position you want to start reading from bytes. Since bytes is reinstantiated every time progress() is called you should always start your reading and writing from a position of 0.

NoobsArePeople2
  • 1,986
  • 14
  • 21
  • Sorry I have to -1 this answer. thisStart is the offset from his last iteration. He doesn't want to re-read the same bytes over and over again. He wants to pick up from where he last left off. Reading bytes from a byte array does not remove them from that bytearray – The_asMan Feb 16 '12 at 18:35
  • @The_asMan [Read the docs](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLStream.html#readBytes%28%29): "The offset _into_ bytes at which data read should begin. Defaults to 0". – NoobsArePeople2 Feb 16 '12 at 18:51
  • Yes begins at zero for first iteration. Second iteration he wants to start reading where the first iteration left off. And third iteration where the second left off. As data is streamed in it is added to the byteArray not replacing the data. – The_asMan Feb 16 '12 at 18:58
  • This is the benefit of streaming something. You only need to handle the new data arriving. Doing it your way would only work if he rewrote the data in the file each time, which would be redundant and slower. – The_asMan Feb 16 '12 at 19:01
  • (I know this is old, but this if for the benefit of anyone coming across this.) The way the code is structured, the offset should `0`, not `thisStart`. Lets say `thisStart` is 10,000 and there are 1,000 bytes available. The readBytes will allocate 11,000 bytes in the ByteArray and write data to the last 1000, then the read will read out those same 1000 bytes. Each time this is called with larger values for `thisStart` a larger ByteArray will be allocated. This is a good way to chew through a lot of memory. (Just fixed this in some legacy code ;-) – Devon_C_Miller Mar 25 '13 at 22:38
0

From what I can tell the image is being cached which would cause an instant load of the file.
Your code does not deal with that since in your complete function you are not doing fileStream.writeBytes which would make for an empty file.
This is not tested code but you need to do something like this.

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;
}
The_asMan
  • 6,364
  • 4
  • 23
  • 34