Reputation: 2869
In my AIR app, I am trying to implement a file downloader using URLStream.
public class FileDownloader { // Class to download files from the internet // Function called every time data arrives // called with an argument of how much has been downloaded public var onProgress :Function = function(loaded:Number, total:Number):void{}; public var onComplete :Function = function():void{}; public var remotePath :String = ""; public var localFile :File = null; public var running:Boolean = false; public var stream :URLStream; private var fileAccess :FileStream; public function FileDownloader( remotePath :String = "" , localFile :File = null ) { this.remotePath = remotePath; this.localFile = localFile; } public function load() :void { try { stream = null; if( !stream || !stream.connected ) { stream = new URLStream(); fileAccess = new FileStream(); var requester :URLRequest = new URLRequest( remotePath ); var currentPosition :uint = 0; var downloadCompleteFlag :Boolean = false; // Function to call oncomplete, once the download finishes and // all data has been written to disc fileAccess.addEventListener( "outputProgress", function ( result ):void { if( result.bytesPending == 0 && downloadCompleteFlag ) { stream.close(); fileAccess.close(); running = false; onComplete(); } }); fileAccess.openAsync( localFile, FileMode.WRITE ); fileAccess.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent) { trace('remotePath: '+remotePath); trace('io error while wrintg ....'+e.toString()); }); stream.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent) { trace('remotePath: '+remotePath); trace('There was an IO error with the stream: '+e.text); }); stream.addEventListener( "progress" , function (e:ProgressEvent) :void { var bytes :ByteArray = new ByteArray(); var thisStart :uint = currentPosition; currentPosition += stream.bytesAvailable; // ^^ Makes sure that asyncronicity does not break anything try { //trace('reading from '+remotePath+' ...'); stream.readBytes( bytes, thisStart ); fileAccess.writeBytes( bytes, thisStart ); } catch(err:Error) { trace('remotePath: '+remotePath); trace('error while writing bytes from...'+err.name+':'+err.message); if(stream.connected) stream.close(); abort(); onComplete(); return; } onProgress( e.bytesLoaded, e.bytesTotal ); }); stream.addEventListener( "complete", function () :void { downloadCompleteFlag = true; }); stream.load( requester ); } else { // Do something unspeakable } running = true; } catch(err:Error) { trace('error while downloading the file: '+err); } } public function abort():void { try { stream.close(); trace('stream closed'); running = false; } catch(err:Error) { trace('error while aborting download'); trace(err); } } }
I simply create an object of the above class and passing the url and the file and call the load function. For some files I get the following error.
remotePath: http://mydomain.com/238/6m_608-450.jpg error while writing bytes from...Error:Error #2029: This URLStream object does not have a stream opened.
Which means the error is from the file stream(fileAccess) that I am using. I am unable to figure out why this could be happening. If I try to open the url http://mydomain.com/238/6m_608-450.jpg
in the browser, it opens properly. This happens randomly for some files. What could be the problem?
Upvotes: 0
Views: 3201
Reputation: 694
I have tried in my office and it works for me (for differents files and filesize). So, can you describe the files (or types files) which don't work for you (post an url if you can) ? I would say that when you use the method readBytes your stream (so the URLStream) is ever close.
More, I allows me some advice : 1/ Use flash's constants instead of simple string 2/ Don't forget to remove your listeners once the operation completed 3/ Your method FileDownloader is quite confusing. Use lowercase if it's a function or puts a capital letter with class's name if you use it as a constructor. For me, this function must be a constructor.
Upvotes: 1