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

  • sideDoor

    Hey Mr Braitsch,

    Thanks so much for this class…this is great work and super handy!

    Trying to implement this, I’m getting this 1010 Error:

    TypeError: Error #1010: A term is undefined and has no properties.
    at com.viewi::body/onImagesLoaded()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at com.quietless.bitmap::ImageBatchLoader/checkImageQueue()
    at com.quietless.bitmap::ImageBatchLoader/ioErrorHandler()

    I’m wondering if it’s because the swf can’t find the php file, or the php file can’t find the image directory, err, I’m not sure…

  • Stephen Braitsch

    @Sidedoor,

    I just updated this post with a much cleaner implementation than before with more comments to help you understand what is going on. Try the new zip and let me know if you have any problems.

  • sideDoor

    Thanks so much! This is a great utility!

    Oops, it appears the link to the sample files is not finding the zip file…I’ll check back later…

    Thanks Mr Braitsch!

  • Stephen Braitsch

    Ah, linked fixed. Sorry about that.

  • sideDoor

    Great work! Again, this is a really handy approach. I got this to work locally, and I could see it being valuable in many situations.

    My only reservation in using php in this case is that it seems from within the Flash IDE, I cannot test the movie and call the php script. In this case, I get this message in the output panel:

    [ HTTPRequest ] : Setting Request.URL To : php/directory-reader.php

    And the movie won’t run beyond this point, which means it makes it difficult to develop a project while using this method if you’re testing your swf from within the Flash IDE. Instead, it seems you’d have to test your development in your browser, which makes debugging maybe not so efficient. Or maybe I’m missing something…

    But the alternative is to return to loading expected images from XML data…hmm…

    Thanks again, I’ll goof around with this package.

    sd

  • http://flashdevelop.org BackDoor

    Mr. Sidedoor!

    Try downloading WAMP (as long as you are windows based) or some other server solution (like LAMP if you are linux based) and try working from its www folder.

    That way all php and other server scripts will work when you are testing your FlashMovie locally.

    By googling WAMP you should have no difficulty finding the correct page, and it’s as easy as download-install-action.
    (it also includes loads of info/tuts etc.. for peeps who are into screwing around with servers, -not me!)

    Yours Truly
    Mr. BackDoor.

  • sideDoor

    @backdoor

    Yeah, hehe, thanks, I’m running Apache 2 and the rest of the deal…I can test this package locally, successfully , but in a browser only…my problem was testing it from within the Flash IDE (Ctrl-Enter): as mentioned, I get this message:

    [ HTTPRequest ] : Setting Request.URL To : php/directory-reader.php

    But before gumming-up this post any further, I’ll first read-up on sending and receiving variables from Flash to php in AS3.

    Before, in AS2, I was using LoadVars to pass variables to and from php scripts, and was able to test these scripts from within the IDE, but anyway, I’ll read up on this, thanks!

    Stephen, again, thanks for sharing!

  • Stephen Braitsch

    Make sure Apache is running and change your path from ‘php/directory-reader.php’ to ‘http://localhost:8888/php/directory-reader.php” and you should be able to test from within the Flash IDE.

  • Ally

    Hi, I was just wondering if you can view more then three images at a time? I tested it out on my server and even though it would say it has loaded all 6 images, it only displays three of them.

    Thanks

  • Stephen Braitsch

    There currently is no limit to the number of images the script can upload. You may want to extend the class and write a handler that waits for one image to finish uploading before starting the next in a queue.

  • http://www.celavi.fr vinzcelavi

    Not yet check this out but it looks really fine !!

    Thanks a lot for your work, I find out your trick in less than 10 seconds on Google !

    Web ressources is wonderful ;-)

  • http://www.elapas.lv Lauris

    Hi! This is a nice utility and it would be really great to use it in my projects. Stephen, please advise if it is allowed to use your class in my commercial projects.

    Thanks in advance
    Lauris

  • Stephen Braitsch

    You are welcome to use any of my code on this site in your commercial projects unless noted otherwise at the top of the class file.

  • Newbie

    Hi,

    I am new to flash. This is a wonderful example.

    Could you point me in the right direction as to how you would go about extending the class so that it waits for one image to finish uploading before starting the next in the queue.

    Many thanks.

  • http://www.lanegoodkind.com Lane Goodkind

    Many thanks to you for posting this. I’ve wondered for a long time how to do this. Works great on my system using MAMP. However when I upload to hosting site no dice. Any suggestions? I’m pretty dumb with PHP but good with as3.