mike chambers | about

Reading and Writing Local Files in Flash Player 10

Wednesday, August 20, 2008

One of the new features in Flash Player 10 are new ActionScript FileReference APIs that allow Flash content to directly read and write data to the user’s system.

Prior to Flash Player 10, in order to read or write a file to the user’s system, Flash content would first have to bounce it off of a server, and then load it back to the users system before it could be accessed. This was not only a hassle to program, but added additional application latency and resource usage.

The new functionality is achieved through the addition of two new APIs on the FileReference class:

FileReference.load() : Loads data from a file selected by the user.
FileReference.save() : Saves data to a file location selected by the user.

A couple of points to keep in mind:

Below are two examples that show how to use the APIs. The examples use Flex for the UI, but the ActionScript is the same regardless of whether you are using Flex or not. The examples are fully commented.

Read a file from the users system:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

    <mx:Script>
        <![CDATA[
            import flash.net.FileReference;
            import flash.net.FileFilter;
            
            import flash.events.IOErrorEvent;
            import flash.events.Event;
            
            import flash.utils.ByteArray;
        
            //FileReference Class well will use to load data
            private var fr:FileReference;
            
            //File types which we want the user to open
            private static const FILE_TYPES:Array = [new FileFilter("Text File", "*.txt;*.text")];
        
            //called when the user clicks the load file button
            private function onLoadFileClick():void
            {
                //create the FileReference instance
                fr = new FileReference();
                
                //listen for when they select a file
                fr.addEventListener(Event.SELECT, onFileSelect);
                
                //listen for when then cancel out of the browse dialog
                fr.addEventListener(Event.CANCEL,onCancel);
                
                //open a native browse dialog that filters for text files
                fr.browse(FILE_TYPES);
            }
            
            /************ Browse Event Handlers **************/
            
            //called when the user selects a file from the browse dialog
            private function onFileSelect(e:Event):void
            {
                //listen for when the file has loaded
                fr.addEventListener(Event.COMPLETE, onLoadComplete);
                
                //listen for any errors reading the file
                fr.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
                
                //load the content of the file
                fr.load();
            }
            
            //called when the user cancels out of the browser dialog
            private function onCancel(e:Event):void
            {
                trace("File Browse Canceled");
                fr = null;
            }
            
            /************ Select Event Handlers **************/
            
            //called when the file has completed loading
            private function onLoadComplete(e:Event):void
            {
                //get the data from the file as a ByteArray
                var data:ByteArray = fr.data;
                
                //read the bytes of the file as a string and put it in the
                //textarea
                outputField.text = data.readUTFBytes(data.bytesAvailable);
                
                //clean up the FileReference instance
                
                fr = null;
            }
            
            //called if an error occurs while loading the file contents
            private function onLoadError(e:IOErrorEvent):void
            {
                trace("Error loading file : " + e.text);
            }
            
        ]]>
    </mx:Script>


    <mx:Button label="Load Text File" right="10" bottom="10" click="onLoadFileClick()"/>
    <mx:TextArea right="10" left="10" top="10" bottom="40" id="outputField"/>
    
</mx:Application>

Write a file to the users system:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

    <mx:Script>
        <![CDATA[
            
            import flash.net.FileReference;
            
            import flash.events.IOErrorEvent;
            import flash.events.Event;
        
            private static const DEFAULT_FILE_NAME:String = "example.txt";
        
            //FileReference Class well will use to save data
            private var fr:FileReference;
                        
            
            /********** UI Event Handlers **************/
            
            //called when the users types in the textarea
            //note valueCommit should be used, but is broken in the flex build 
            //I am using
            private function onInputChange():void
            {
                //enable button if there is any text to save
                saveButton.enabled = (inputField.text.length > );
            }
            
            //called when the user clicks the load file button
            private function onSaveClick():void
            {
                //create the FileReference instance
                fr = new FileReference();
                
                //listen for the file has been saved
                fr.addEventListener(Event.COMPLETE, onFileSave);
                
                //listen for when then cancel out of the save dialog
                fr.addEventListener(Event.CANCEL,onCancel);
                
                //listen for any errors that occur while writing the file
                fr.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
                
                //open a native save file dialog, using the default file name
                fr.save(inputField.text, DEFAULT_FILE_NAME);
            }
            
            /***** File Save Event Handlers ******/
            
            //called once the file has been saved
            private function onFileSave(e:Event):void
            {
                trace("File Saved");
                fr = null;
            }
            
            //called if the user cancels out of the file save dialog
            private function onCancel(e:Event):void
            {
                trace("File save select canceled.");
                fr = null;
            }
            
            //called if an error occurs while saving the file
            private function onSaveError(e:IOErrorEvent):void
            {
                trace("Error Saving File : " + e.text);
                fr = null;
            }
        ]]>
    </mx:Script>


    <mx:Button label="Save File" right="10" bottom="10" id="saveButton" 
                                            click="onSaveClick()" enabled="false"/>
    <mx:TextArea right="10" left="10" top="36" bottom="40" id="inputField" 
                                    editable="true" change="onInputChange()"/>
    <mx:Label text="Enter text to save" left="10" top="10" fontWeight="bold"/>
    
</mx:Application>

In addition to the events shown in the examples above, the following events are also broadcast by the APIS:

While it will also be possible to use these APIs in Adobe AIR, in general, you will want to use the AIR File APIs as they provide more functionality and flexibility.

You can download the Flash Player 10 ActionScript APIs docs from here.

You can find more information on Flash Player 10 on labs.

twitter github flickr behance