Reading a Text File
The first thing we need to do, is to give the user a place to click. All file access operations must be initiated from a mouse click in the Flash Player. This does not mean that your entire user interface (UI) needs to be delivered via the Flash Player. In this case we will use a single button - the button that the user would otherwise click on to start the file access operation.
btnup = new Loader();
addChild( btnup );
btnup.addEventListener( MouseEvent.CLICK, doClick );
protected function doClick( event:MouseEvent ):void
You will notice in this case that rather than use the Flash Player vectors to draw the artwork for the button, that I am loading the names of images from the HTML parameters to use for the various button states. This lets you further control the appearance of the button without having to change or recompile the code. In other words customization without having to know anything about developing for the Flash Player.
The class that does all the heavy lifting for us here is the FileReference class. When the user clicks on the button, we will use the FileReference.browse() method to allow them to select a file. To know when they have selected a file we will also want to listen for the Event.SELECT event. Once this event has been received, we can call FileReference.load() to read the physical contents of the file.
file = new FileReference();
file.addEventListener( Event.SELECT, doFileSelect );
file.addEventListener( Event.COMPLETE, doFileLoaded );
protected function doFileSelect( event:Event ):void
protected function doFileLoaded( event:Event ):void
var data:String = null;
data = file.data.readMultiByte(
ExternalInterface.call( "setData", data );
Keep in mind that the data file you load from the users system will need to be loaded into memory, so this might not be best for a multi-gigabyte movie file. The Flash Player itself however, has been tested to files as large as 100 Mb which gives you a lot of breathing room. You can get progress events as the file gets loaded, but in this case I am only going to worry about when the entire file read operation is complete.
var setdata:String = loaderInfo.parameters["setdata"];
ExternalInterface.call( setdata, data );
// Using jQuery
function setData( data )
$( '#edit' ).attr( 'value', data );
Saving a Text File
Remember earlier that I noted that load and save operations needed to be initiated by a user mouse click in the Flash Player. If we want to save that changed content back into the file it came from, then we will need to let the user initiate that with a button presented in the Flash Player. Again, the images for the button are loaded from HTML parameters to the Flash Player object.
var data:String = ExternalInterface.call(
var bytes:ByteArray = new ByteArray();
bytes.writeMultiByte( data, "utf-8" );
file.save( bytes, "myfile.txt" );
With the ByteArray populated, we can pass it to the FileReference.save() method call. The result will be a dialog box presented to the user. At this point all the programming work is done. The user on the other hand has a couple options. While you can specify a default name, the user can change it if they prefer something else. They also get to choose where to save the file.
Saving Image Files from Canvas
Among the exciting new features of the HTML5 specification, is support for CANVAS. This blank slate opens the door to all fashion of different visualizations. In the following example I let the user draw a picture using their mouse. The question then becomes, how do you let the user save the picture to their local system? Once again we find ourselves caught in the upload, process, send workflow.
As it turns out, canvas actually gives you access to the raw pixel data that has been drawn. This might be user generated content, mathematically generated content, image content and more. Since you now have the ability to save content without the round-trip to the server, you might be inclined to send an array of pixels over to the Flash Player, let it encode them to an image format, and then save the file out to disk. And for the most part, you would be successful.
Wait? Encoding images? Sure! There are ActionScript libraries that do JPEG, PNG, BMP and more. You pass in pixels, and get back the bytes of an image. Sweet!
Well, not so fast! Encoding an image takes time. That is a lot of number crunching to be sure. For example, a canvas that is a small 200 pixel by 200 pixels space is 40,000 pixels. Each pixel consists of three values (red, green, and blue), which means 120,000 items to be reviewed at a bare minimum. And 200x200 is not much creative space. The larger the canvas, the more time it will take to encode that image.
While ExternalInterface is pretty snappy, passing an array of 120,000 integers will also slow us down.
// Get the Base64 encoded PNG
// Inspired by http://bit.ly/930WOF
// Sending raw pixels is slow
// Let the native browser do the work
return document.getElementById( 'stage' ).toDataURL();
var png:ByteArray = null;
var start:Number = 0;
var data:String = null;
data = ExternalInterface.call( "getImageData" );
start = data.indexOf( "," ) + 1;
png = Base64.decodeToByteArray(
data.substr( start, data.length - start )
file.save( png, "fromjs.png" );
Just as there are ActionScript libraries for encoding images, there are also ActionScript libraries for working with base-64. In this case we can use one such library, the ActionScript Core Library (open source), to get the bytes back out of the encoded string by calling Base64.decodeToByteArray(). Once we have our ByteArray, we can call the FileReference.save() method. At that point the user gets prompted to save the file.
It may sound a little more complex for this image approach, but it all happens in the blink of an eye, even with a larger canvas.
The Big Picture
Part of the reason we are seeing the web standards expand to include more functionality, is because users are demanding more compelling interfaces, and ultimately experiences. These demands result in application requirements that were not originally envisioned with the previous specifications. The interesting paradox that emerges is that it is much harder to differentiate yourself on user experience if everybody is using the same standards.
To that end, browsers have plug-in APIs for content such as Flash Player. These plug-ins are not constrained by the standards process, and are free to innovate as fast as the market allows. In the case of the Flash Player, that has been roughly one iteration every year, that is broadly distributed and nearly ubiquitous in about one year after that. Does that mean you have to go all in on Flash? No!
Download the source code for these examples to add local file access to your toolbox.
NOTE: The above ActionScript programs can be compiled using the freely available and open source, Flex SDK. Should you desire a developer IDE, Flash Develop is a good open source option, Flash Builder is the commercial Adobe offering, and you can even use Visual Studio via the Amethyst plug-in from Sapphire Steel. Or you know, if SWF provided here does what you need, then that works too.