AS3 Image Batch Loader with PHP Directory Browsing

Updated: February 4. 2009 – Much cleaner implementation with added comments to hopefully help you understand what is going on

In this being a utility I have been meaning to improve on for awhile, this post attempts to tackle two tasks that are especially common in Flash Platform development. 1st the need to load in a batch of images sequentially and 2nd the ability for Flash to be able to ‘see’ inside of a directory on the filesystem and load all the available images within.

As is common knowledge, Flash by itself cannot measure the contents of a directory but PHP conveniently can and report back to Flash its findings. This is all accomplished by loading the included PHP script ‘directory-reader.php’ into an AS3 URLLoader object and capturing the variables PHP echoes back to it.

Consider the following:

public function ImageLoadManager ()
{
   var dr = new DirectoryReader(_pathToDirectory,  '*');
   dr.addEventListener(HTTPRequestEvent.COMPLETE, onDirectoryRead);
}

We create a DirectoryReader object and pass into it the path to the directory we want to read relative to the location of the php script on the filesystem. (We’ll talk about where that script goes in a second). It should be noted that many PHP installations have URL file-access disabled in the server configuration by default which may throw errors if you try to provide absolute URL’s. You many need to change your config file to get around this or just use a relative URL as the sample files provided do instead.

Since this utility was designed to gather all of the image files from a directory that Flash supports, (jpg, png, and gif), it will do just that if you leave the second parameter blank. If you are interested in seeing every visible file in the directory (not including sub-directories) you can pass in a wildcard flag ( * ) as shown in the example above. Note the array of file names this returns will include non-image filetypes which will throw IO errors if you pass them into the ImageBatchLoader in the next step.

After we’ve created our DirectoryReader we’ll want to listen for the ‘HTTPRequestEvent.COMPLETE’ event that gets fired when the PHP script is successfully executed. In the onDirectoryRead function below we can access the array of file names that came back from PHP through the data property of HTTPRequestEvent object.

private function onDirectoryRead(evt:HTTPRequestEvent):void
{
  _files = evt.data as Array;
}

We can then take this list of files and pass it into a new ImageBatchLoader object that will naturally go and load up our images.

private function onDirectoryRead(evt:HTTPRequestEvent):void
{
  _files = evt.data as Array;
// load a batch of images //
  _loader = new ImageBatchLoader(_files, _swfToImages);
  _loader.addEventListener(ImageBatchEvent.IMAGE_PROGRESS, 
   onImageLoadProgress);
  _loader.addEventListener(ImageBatchEvent.BATCH_PROGRESS, 
   onImageBatchProgress);
  _loader.addEventListener(ImageBatchEvent.BATCH_COMPLETE, 
   onImageBatchComplete);	
}

An instance of the ImageBatchLoader class expects at least one parameter, an array of file names to load. Once it has this it will load each image one by one and trace out a whole slew of loader event info to the console so you can monitor each image load’s progress. (Note: To view this output set the debug property of _loader to true) The second parameter is a relative path to the directory where the images to be loaded reside. It should be noted that this path will almost always be different from the path you fed to DirectoryReader since it needs to be relative to the location of the published SWF on the filesystem, NOT the location of the PHP file as we noted above.

Of course you can create a list of files names via a remoting call that polls a database or by reading in an XML file. The purpose of this technique to address those situations where you need a fast and lightweight solution to ‘peek’ inside a directory and grab however many images are in it.

This can all be accomplished with the following sample of code:

package {
import flash.display.Sprite;
import flash.events.MouseEvent;
 
import com.quietless.utils.DirectoryReader;
import com.quietless.bitmap.ImageBatchLoader;
import com.quietless.events.ImageBatchEvent;
import com.quietless.events.HTTPRequestEvent;
 
public class ImageLoadManager extends Sprite
{
private var _loader:ImageBatchLoader;
private var _files:Array; // all files names returned by php //
private var _bitmaps:Array;// all bitmaps successfully loaded //
// path from the published swf to the image folder //
private var _swfToImages:String = 'images/';	
// path from the php script to the directory you want to browse //	
private var _phpToImages:String = '../images';	
 
public function ImageLoadManager ()
{
   var dr = new DirectoryReader(_phpToImages, '*');
   dr.addEventListener(HTTPRequestEvent.COMPLETE, onDirectoryRead);
}
 
private function onDirectoryRead(evt:HTTPRequestEvent):void
{
   _files = evt.data as Array;
// load a batch of images //
   _loader = new ImageBatchLoader(_files, _swfToImages);
   _loader.debug = false;
   _loader.addEventListener(ImageBatchEvent.IMAGE_PROGRESS, 
   onImageLoadProgress);
   _loader.addEventListener(ImageBatchEvent.BATCH_PROGRESS, 
   onImageBatchProgress);
   _loader.addEventListener(ImageBatchEvent.BATCH_COMPLETE, 
   onImageBatchComplete);			    
}
 
private function onImageLoadProgress(evt:ImageBatchEvent):void
{
   var bl:Number = evt.data.loaded;
   var bt:Number = evt.data.total;
   log( 'Loading Image # '+evt.data.position+' : '+bl+' of
   --> '+bt+' Bytes Loaded = '+Math.ceil((bl/bt)*100)+' %' );
}
 
private function onImageBatchProgress(evt:ImageBatchEvent):void
{
   log('Successfully Loaded '+evt.data.loaded+' of 
   --> '+evt.data.total+' Images In This Batch');
}
 
private function onImageBatchComplete(evt:ImageBatchEvent):void
{
   _bitmaps = evt.data as Array;
   var img = _bitmaps[0]; 		
   addChild(img);
   log('Image Batch Load Complete!!');
}

As for the business of where to put the PHP script that can actually read the directory you specify? I have it set as a constant variable inside of the DirectoryReader class:

private static const PATH_TO_DIRECTORY_READER:String =
   'http://localhost:8888/php/directory-reader.php';

My Mamp installation points to my project root folder which contains a ‘php’ folder (containing ‘directory-reader.php’), an ‘images’ folder that contains my images and of course the published swf and an html page. Note you will need to have a server running PHP 5 locally if you want to test the sample files from the Flash IDE.

If you have any questions please post in the comments below.

Sample Files

  • venu

    great thanks