Downloading large files in Adobe AIR with Flex

19 June, 2008 (21:35) | Adobe AIR / Flex | By: Jarin Udom

Everyone is probably familiar with the method for downloading files provided in the Flex documentation:

var urlString:String = "http://example.com/myfile.zip";
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
 
function loaded(event:Event):void {
  urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
  writeFile();
}
 
function writeFile():void {
  var file:File = File.desktopDirectory.resolvePath("myfile.zip");
  var fileStream:FileStream = new FileStream();
  fileStream.openAsync(file, FileMode.WRITE);
  fileStream.writeBytes(fileData, 0, fileData.length);
  fileStream.close();
}

The only problem with this is the file data is stored in memory until you write it to disk. Obviously this will not work well for large files (on the order of hundreds of megabytes).

Here's a better way to download large files that works by using the progress event to write bytes to disk as they come in:

var urlString:String = "http://example.com/myfile.zip";
var urlReq:URLRequest = new URLRequest(urlString);
private var urlStream:URLStream = new URLStream();
private var fileStream:FileStream = new FileStream();
 
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.addEventListener(ProgressEvent.PROGRESS, writeFile);
 
var file:File = File.desktopDirectory.resolvePath("myfile.zip");
fileStream.openAsync(file, FileMode.WRITE);
 
urlStream.load(urlReq);		
 
function writeFile(event:ProgressEvent):void {
  // only write every 50k or so downloaded
  if (urlStream.bytesAvailable > 51200) {
    // Read the buffer into a ByteArray and write it to disk
    var data:ByteArray = new ByteArray();
    urlStream.readBytes(data, 0, urlStream.bytesAvailable);
    fileStream.writeBytes(data, 0, data.length);
  }
}
 
function loaded(event:Event):void {
  // Write any remaining data to the file before closing it
  var data:ByteArray = new ByteArray();
  urlStream.readBytes(data, 0, urlStream.bytesAvailable);
  fileStream.writeBytes(data, 0, data.length);
  fileStream.close();
}

Enjoy!

Comments

Comment from Norbert
Date: August 10, 2008, 2:52 pm

Thanks!

Please remove the fileClosed reference since there’s no such variable defined.

Your code works with Javascript as well if you make the necessary modifications to the syntax.

Comment from Jarin Udom
Date: August 11, 2008, 10:40 am

Good call, I’ve fixed it. Thanks!

Write a comment