Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download a file with Adobe AIR

How do I download a file from the internet in a Flex based AIR application.

I tried using a file with url set to the address, but I got a file does not exist error when I tried to save it. And it is really hard to google for help on this issue.

like image 315
AlexH Avatar asked Dec 05 '08 05:12

AlexH


2 Answers

You want to choose from 2 api combos to accomplish this.

Version 1 is URLLoader and FileStream

Using this combination of class, you would load the file from your server in to air via the URLLoader object. This will download the file in to memory and then notify you when the download is complete. Make sure you initiate the download with a dataFormat of URLLoaderDataFormat.BINARY. You would then initiate a Filestream object and write it out to the disk using writeBytes().

Version 2 is URLStream and FileStream

URLStream is very similar to URLLoader, but instead of waiting for the file to completely download before using the result, data is made available to you during the download. This method works well for large files because you don't have to wait for the full download to start saving it to disk, and you also save on memory since once the player hands it off to you it can release the memory related to that data. YOu would use filestream in exactly the same way, you would just end up doing a writeBytes() on each chunk of the file as it streams in.

like image 60
seanalltogether Avatar answered Oct 16 '22 00:10

seanalltogether


I used seanalltogether's answer, and wrote this class to handle file downloading.

It is pretty simple. create a var downloader = new FileDownloader("url", "Local/Path"); and call downloader.load() to start downloading.

It also supports setting a function to be called when done, and at points while downloading. Passing the onProgress function the number of bytes that have been downloaded. ( I could not figure out how to get a fraction, since I could not figure out how to query the size of the file before it was downloaded)

package com.alex{
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.utils.ByteArray;

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(t:uint):void{};
    public var onComplete :Function = function():void{};
    public var remotePath :String = "";
    public var localFile :File = null; 

    private 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 {
        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();
                    onComplete();
                }
            });

            fileAccess.openAsync( localFile, FileMode.WRITE );

            stream.addEventListener( "progress" , function () :void {

                var bytes :ByteArray = new ByteArray();
                var thisStart :uint = currentPosition;
                currentPosition += stream.bytesAvailable;
                // ^^  Makes sure that asyncronicity does not break anything

                stream.readBytes( bytes, thisStart );
                fileAccess.writeBytes( bytes, thisStart );

                onProgress( currentPosition );                      
            });

            stream.addEventListener( "complete", function () :void {
                downloadCompleteFlag = true;
            });

            stream.load( requester );

        } else {
            // Do something unspeakable
        }
    }
}}
like image 14
AlexH Avatar answered Oct 16 '22 00:10

AlexH