AIR: How to save locally a resource from Web

I am working on a very, very cool AIR project. I can’t say much about it for now, but in a couple of weeks I hope it will be released, and then I will blog about it. Anyway, while working on this project I had to implement different work flows revolving around online/offline status. One thing you often want to do in an AIR application is: save resources from the web to the local machine, either to make them available to the application even when a network connection isn’t available or just to optimize bandwidth usage.

That’s what this article is about. I will show you a simple snippet of code that just does the job. Here is the exported AIR project (download it, and you can import the archive using Import > Flex Builder > Flex Project) and here is the the application code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
    <mx:Script>
        <![CDATA[
        import mx.controls.Alert;

        /**
         * loader object used to load content from web
         */
        private var loader:URLLoader = new URLLoader();

        /**
         * This function gets called when the application was loaded.
         * Initialize the loader object.
         */
        private function init():void {
            //we want to download images and other binary resources, 
            //so I overwrite the default value text to Binary
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            //attach the event listeneri for load event and errors event
            loader.addEventListener(Event.COMPLETE, onLoad);
            loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
        }

        /**
         * This is the click handler for the button in page.
         * Just triger the load and disable the button so no other 
         * request can be sent while it is already running one.
         */
        private function saveResource():void {
            loader.load(new URLRequest(resURL.text));
            btn.enabled = false;
        }

        /**
         * This function gets called when the resource was loaded.
         * We just extract the name of the resource and call the saveLocally() function
         * to write the object on the local machine.
         */
        private function onLoad(event:Event):void {
            btn.enabled = true; //enable the button so we can send another request.
            var fileName:String = new String(resURL.text).split("/").pop();
            //call the saveLocally function; loader.data has the bytes of the loaded resource
            saveLocally(fileName, loader.data);
        } 

        /**
         * Error handler for loader object. 
         * I just display the error message and enable the button for new requests.
         */
        private function onError(event:ErrorEvent):void {
            btn.enabled = true;
            Alert.show(event.text, "Error");
        } 

        /**
         * This function does the actual saving.
         * @param file name to be used for saving
         * @param bytes to be written
         */
        private function saveLocally(fileName:String, data:ByteArray):void {
            //create a file under the application storage directory using the filename argument
            var file:File = File.applicationStorageDirectory.resolvePath(fileName);
            if (file.exists)
                file.deleteFile(); //delete it if exists
            //create a file stream to be able to write the content of the file    
            var fileStream:FileStream = new FileStream();
            //open the file stream and set for Write
            fileStream.open(file, FileMode.WRITE);
            //writes the bytes
            fileStream.writeBytes(data, 0, data.length);
            //close the stream
            fileStream.close();
            //display the path of the saved resources    
            showLocalPath.text = file.nativePath;
        }
        ]]>
    </mx:Script>
    <mx:VBox width="820" x="10" height="200" y="10">

        <mx:Label text="Save a web resource locally"  fontSize="26"/>
        <mx:Label text="Enter a resource URL such as http://mysite/image.jpg" />
        <mx:HBox>
            <mx:TextInput id="resURL" text=""  width="600"/>
            <mx:Button id="btn" click="saveResource()" label="Save locally" />
        </mx:HBox>
        <mx:Label id="showLocalPath" />
    </mx:VBox>
</mx:WindowedApplication>

Here is an explanation of what I did:

Comments

2 Responses to “AIR: How to save locally a resource from Web”

  1. jecson brad on August 6th, 2008 12:29 pm

    I set this property to I attach some functions to my loader for Complete and Error events.

  2. Storing data locally in AIR : Mihai CORLAN on September 2nd, 2008 7:05 pm

    [...] You can read more on this here. [...]

Leave a Reply