| Register
Saturday, May 17, 2008   

Preloading Files into the Browser's Cache

Created By  Satori Canton, at  5/17/2006 - 31 comments.

Click to view this author's website.

I've been planning since last year to revise my Tile Effects Component and make something similar that would work to load external images, rather than loading images from the library. I've finally set some time aside to work on this. I've decided to make it a series of ActionScript classes, rather than another component. A lot of the elements involved are actually very useful in other applications and packaging them up into a component would hide that.

The first thing that I need to create the new Tile Effects Classes is a class that will ensure that the content I want to use (in this case images, but I want to make this class generically load anything) is actually loaded to the client and available to use. I want to be able to pass the class an array of file paths, and then check back with the class to see what's already been *successfully* loaded. Successfully loaded is important. Since the class is going to manage this preloading, it should be able to detect failed loads.

What I ended up creating is a small class (only 46 lines of code) called FilePreloader (source code).

This class implements a strategy that I've written about before. It uses a trick with the LoadVars object in Flash to load files into the browser's cache, but not actually into Flash. The way the LoadVars object works is to load data (it's expecting text data, but it can be any kind of data including images) into the browser's cache. Once there, it can read the data. It won't be able to parse image data, and will fail silently. But the data stays in the browser cache and can be loaded immediately on demand. LoadVars also tells you if the data was successfully loaded or not (if the file doesn't exist, it will tell you that the load failed). So this gives us the functionality of detecting that the paths to the files are valid, so we can filter out missing files.

Using the class is pretty simple. Once you create an instance of the class, you call its preload() method and pass it an array of strings that represent paths to the files you want to load. Then, when you want to load content that's already in the browser's cache, you just access the class' "loadedItems" property to get an array of paths that are already in the cache. For example:

After a moment, you'll be able to access fp.loadedItems to get an array of files that are currently loaded into the browser's cache. Simple, but very useful.

I'll have more as I write the other classes for the new Tile Effects classes. I'll publish them as they're complete.

Need Professional Help For Your ActionScript Project?
ActionScript.com Consulting Services provide top quality professional ActionScript consulting to businesses around the globe. If you have a professional project in need to world-class talent, tell us about your project by requesting a quote today.

Reader Comments

  1. BD  Replied:
    ( 5/17/2006 At 5:20 PM)

    HI ---

    Thanks for the article. I am guessing that it is something I am doing wrong, however when I call fp.loadedItems it doesn't return anything. The onLoadHandler never seems to get executed (based upon trace statements)

    Thanks for the help.

  2. Jeff Chadwell  Replied:
    ( 5/17/2006 At 6:38 PM)

    Does this same trick also work for loading XML documents?

  3. Satori Canton  Replied:
    ( 5/17/2006 At 11:32 PM)

    BD,

    Not sure what's going on with that. I'll put together a working example of the class so you can see it in action and how it will be used in the Tile Effections classes.

    Jeff,

    The same trick would work with XML documents, but I'm not sure it's needed. You can load XML without displaying the results. The real trick here is that you can load images without dealing with displaying them until you're ready for them. But this would give you the option to load any kind of data into the browser cache (even other SWF files) without having to directly work with or display them.

    The other main advantage to this technique is that you can detect that a file actually exists. So, for example, if you had XML files named xml000.xml to xml111.xml and you want to load all xml files between xml000.xml and xml999.xml, this technique would allow you a way to know that files xml12.xml to xml999.xml dont exist (so shouldn't be used). This class will only return successfully loaded files (even though those files can't be parsed by LoadVars).

  4. Harry Vikatos  Replied:
    ( 5/18/2006 At 3:12 AM)

    Hi
    it is not clear to me how this method is different/better from loading for example a jpg into a non-visible movie clip.
    Could you explain?

  5. Satori Canton  Replied:
    ( 5/18/2006 At 8:47 AM)

    This method isn't necessarily "better" than alternatives. It's just one strategy. In this case, it allows us to load any kind of data onto the client (it doesn't necessarily have to be images. I think the main advantage with the technique I chose is that we can detect if the file actually exists. LoadVars will tell us if it's unable to load the file.

  6. Andrei Patriciu  Replied:
    ( 5/18/2006 At 10:09 AM)

    What if the preloaded file contains a sequence like:

    long_var_name=long_var_data

    even if it is a jpeg image or mp3 file

    will the swf try to load its content inside it and set the value to the variable (and fill the memeory with unusefull data) or in the browser cache , or both ?

    It would be interesting to see if after such a preload any new variables are defined.

  7. Satori Canton  Replied:
    ( 5/18/2006 At 10:20 AM)

    Since the http protocol is 100% text based, images, MP3s, even VOIP is ultimately transfered across the internet as encoded text packets. So, when LoadVars makes a load request, that encoded text (that represents the image file in this case) gets loaded into the browser cache. When the data has fully loaded in the cache, LoadVars then trys to process it and create variables in Flash. But in this case, the UUEncoded image is just meaningless text to the LoadVars object, so it silently fails to parse variables out of the data.

    Unless the data coming back is URL encoded data that LoadVars can parse, no additional variables will be defined in Flash.

  8. Michael Welch  Replied:
    ( 5/18/2006 At 10:28 AM)

    To quote your article, "After a moment, you'll be able to access fp.loadedItems ...". What is your suggested method of determining when a 'moment' has passed. Have you considered broadcasting an event when the preloader has finished with the _loadArray?

  9. Satori Canton  Replied:
    ( 5/18/2006 At 10:48 AM)

    Actually, that's a very good idea. The way I was using it currently was to build a slide show. I was just looking for *any* content and not so much interested in being notified when new content arrived. I've updated the class to dispatch load events.

    New source - http://www.actionscript.com/files/satori/FilePreloader.zip

  10. Andrei Patriciu  Replied:
    ( 5/18/2006 At 5:20 PM)

    Regarding the fire of an event I guess it would be util to fire 2 type of events one kind when a file is downloaded onFileCached(e) // e = {fileName:String, succeas:Boolean} this way if you are using it for a slide show you can start showing the image, and the second event when all files have been cached.

    ---------------

    Regarding the content of files and the way Flash interprrets them ... it is true that Flash is checking if it understands the content just after it downloads the file (the XML object does the same?) but after the download ends if the file downloaded has any sense for the Flash it will create variables.
    I have made a test , I have edited one jpeg file and placed at the begin of the file "t=". Everything has been loaded inside and set to var t :)
    BUT , the good part is that I didn't find any image file or sound file or video file that starts with a [a-z] string followed by equal :)
    BUT teoreticaly if the file you are trying to preload starts in a way that Flash is able to interpret , even if it is not url encoded, some variables will be created.
    Though I don't think this tehnique is bad at all :D

  11. Andrew Rapo  Replied:
    ( 6/8/2006 At 4:36 AM)

    I think it's an interesting idea. It would be valuable to load files into the browser cache without using system memory - until the files are needed.

    Overriding the LoadVars decode() method would eliminate the risk of random data being interpreted as variables:

    public function init() {
    _fileArray = [];
    _loadArray = [];
    _lv = new LoadVars();
    _lv.onLoad = Delegate.create(this, onLoadHandler);

    //override the decode() method
    _lv.decode = function() {};
    }

    Andrew

  12. Joel Yabrudy  Replied:
    ( 6/15/2006 At 3:06 PM)

    In terms of accessing fp.loadedItems and using the dispatched load events, can someone please give me some sample code that would handle this?
    Basically I just want my main timeline to play once the files have been loaded.
    Any help would be appreciated.

  13. Marcelo de Moraes Serpa  Replied:
    ( 7/1/2006 At 8:11 AM)

    Very interesting. Thanks for the nice article!

  14. marc lin  Replied:
    ( 7/6/2006 At 5:19 PM)

    I try to use the dispatchEvent in your FilePreloader class.
    Is there any specific reason you choose the word "load" to be your "type" ?(which should be the function name right?)

  15. Satori Canton  Replied:
    ( 7/7/2006 At 12:50 PM)

    "load" is a common name that I often use for events indicating that something has loaded. To catch this event, you'll need to subscribe a listener for the event and define a function to handle the event. As in:

    import com.actionscript.utils.FilePreloader;
    import mx.utils.Delegate;
    
    onLoadHandler = function(o:Object):Void {
    //code to handle the event
    }
    
    myPreloader = new FilePreloader();
    myPreloader.addEventListener("load", Delegate.create(this, onLoadHandler));
    myPreloader.preload(["image1.jpg", "image2.jpg"]);
    

  16. paulo veiga  Replied:
    ( 7/13/2006 At 10:02 PM)

    Hi there!

    Satori do you konw or, does anyone know how to resolve the problem of the "export in first frame"????

    every time i try to make a preloader, i have problens... if i select the first frame, the preloader doesn't show the information...

    if the first frame is not selected, the preloader show the info , but the images doesnt't load :[

    Satori can you help me with this????

    Best regards
    Paulo Veiga

  17. Mark Brenwall  Replied:
    ( 7/17/2006 At 1:31 AM)

    great article but I'm still unclear how to let my timeline know that all the items have been loaded as Joel mentions above.

    Like him, I want to hold on the first frame until all the items have been loaded into cache and THEN play the movie.

    Thanks in advance!!

  18. Satori Canton  Replied:
    ( 7/17/2006 At 12:07 PM)

    If you just want to hold on the first frame and then play once all the files are loaded, you could use:

    import com.actionscript.utils.FilePreloader;
    import mx.utils.Delegate;
    
    stop();
    
    onLoadCompleteHandler = function (o:Object):Void {
       play();
    };
    myPreloader = new FilePreloader();
    myPreloader.addEventListener("loadComplete", Delegate.create(this, onLoadCompleteHandler));
    myPreloader.preload(["image1.jpg", "image2.jpg"]);
    

  19. Mark Brenwall  Replied:
    ( 7/17/2006 At 9:35 PM)

    Thanks for your quick response.
    I did a test with the code above and it is not working for me. You can take a look at the files here:
    http://birch.liquidagency.com/projects/juicy/FilePreloader.zip

    Would love to know what I'm doing wrong.
    Thank you so much!!

  20. Brian McBride  Replied:
    ( 7/20/2006 At 5:48 PM)

    Interesting idea. I only see 2 problems with this method.

    The first is that most browsers only have a limited amount of sockets things can be loaded on. So, if you make 100 load requests don't plan on letting the browser load anything else for a while. That could be tricky if you are waiting for a key .swf file to load. Of course, you cannot even guarentee that that key file will load first if you start it first. Like a website, the actual load order of files can vary depending on the server connection.

    Second, you have no way to know that the user has the cache size that you need. Or if they turn off their cache totally (some people do that sort of thing I suppose). To this end, you would waste time loading an image and having to load it again earlier. And with a huge list of images to load, it could endup taking forever.

    One of the best options is to build yourself a priority queue loader where you can swap the loading priority at any time. With a tool like this, you could build a background loader that allows your application to run and load what it feels is most important to operation in the order it is expecting, and it can background load up those images. Way more code than this example, but it will last you the lifetime or two of a Flash version... maybe more.

  21. gg alan  Replied:
    ( 8/30/2006 At 1:52 AM)

    can anyone post a sample to see how this works please.

    thank you

  22. Niresh Kumar  Replied:
    ( 9/2/2006 At 2:39 AM)

    hi Satori Canton,

    i have a different situation here,

    i have saved an image/swf to database as binary format,

    is it possilbe to use this trick to load that image which is in binary format and load it into flash.

    thank you

  23. chan s  Replied:
    ( 11/23/2006 At 10:15 PM)

    Hi Satori,

    i know this might b a bit outdated, but is my 1st few times involving into actionscript, i was trying to export the file with importing the filepreloader.as file as stated, but it return the following line, plz do guide me on this,
    "The class or interface 'com.actionscript.utils.FilePreloader' could not be loaded.
    var fp:FilePreloader = new FilePreloader();"

    Thanks in advanced

  24. Satori Canton  Replied:
    ( 11/24/2006 At 12:42 AM)

    Chan,

    On the surface, it looks like your not importing the class. Look at the sample files and how the class is imported in the example. If you don't import the class, Flash won't know what "FilePreloader" is.

  25. Daniel Hall  Replied:
    ( 11/28/2006 At 4:22 AM)

    Hi Chan,

    I had this one as well. I was trying to load the preloader from the same directory as the FLA file.

    if you change :

    import com.actionscript.utils.FilePreloader;

    to :

    import FilePreloader;

    Then in the .as file change :

    class com.actionscript.utils.FilePreloader {

    to :

    class FilePreloader {

    That sorted it out for me.

    Cust.

  26. Wai Man Wong  Replied:
    ( 12/4/2006 At 7:54 PM)

    Hi Satori,

    Interesting technique. I have yet to try it but definitely have the same concern as Brian McBride above. Any comment on that?

    My main concern is preloading of the main .swf. Would the main preloader wait or rather, include in its calculation, the preloading of other data using the filePreloader code? In other words, do I need to explicitly preload only what I need and then later execute the filePreloader code? Or does this technique operate independently from the main .swf no matter where/when the filePreloader code is located? Thank you in advance.

    _Wai Man

  27. Satori Canton  Replied:
    ( 12/5/2006 At 1:26 AM)

    Wai,

    Yeah, I agree, Brian McBride's concerns are valid. And in more complex applications, building a priorty queue would be ideal. If you're working with large files, it may note be realistic to count on browser settings (my own are set to zero cache for testing purposes). But in general, this can be an effective technique to preload a file, and then grab it (sometimes repeatedly) from the cache.

    A bigger issue, that I haven't written about before, but has arose in practice is, this technique limits your options for cross-domain data/file access. LoadVars is actually pretty choked back in terms of security. Where as XML.load and MovieClip.load can load across domains with more liberal security settings. So if you have a huge slide show type application with XML being served by one host (outside your own domain) and images hosted somewhere else (also outside your domain), this trick breaks down pretty fast.

    It's fine if you control the app and everything is coming from your domain, and the files loaded are not massive (beyond reasonable cache settings).

    But, in *LARGE scale* applications, I've pretty much given up on this technique. I've been thinking of some alternatives, but haven't decided what the best path would be.

  28. alex Pereira  Replied:
    ( 4/26/2007 At 10:07 AM)

    I just getting my head round this code and the way it works:

    i have
    import com.actionscript.utils.FilePreloader;
    var fp:FilePreloader = new FilePreloader();
    imageArray = ["intro01.jpg", "intro02.jpg", "intro03.jpg", "intro04.jpg", "intro05.jpg"];
    fp.preload(imageArray);

    But how do i call the now preloaded images into an empty MC using the class, as i'm not clear how that bit works?

    cheers
    Alex

  29. Charles Angell  Replied:
    ( 5/22/2007 At 10:46 AM)

    Hi Satori,

    I've been trying to find a method of preloading images into the browser cache. I'm working on a flash website that uses numerous large images for the backgrounds so essentially I'm trying to emulate a javascript preloader - using actionscript. Naturally I was quite happy to come across your article. I have incorporated the script. It seems to work fine, I can enter image paths into the image array and call the fp.preload(imageArray) function. I can then use trace(fp.loadedItems) to see what's been loaded.

    But being a novice with Actionscript I don't understand how to access the cached item. I thought that fp.loadedItems was key to that but it merely recounts the paths of the loaded images. Can you offer any insight on this.

  30. Gideon Farrell  Replied:
    ( 6/23/2007 At 6:26 PM)

    Satori,

    I've been trying to look at the class for a while (I'm relatively new to flash and as etc) and trying to learn from it, but when I try and set it up it doesn't work. I get the message:

    "The class or interface 'com.actionscript.utils.FilePreloader' could not be loaded."

    even when unzipping your file straight into the root directory.

    Any thoughts would be welcomed.

    Thanks,
    Gideon.

  31. jj yang  Replied:
    ( 7/6/2007 At 12:21 PM)

    Hi,

    I am new to AS3 and FLEX. I would to start simple, I load the images into an array in advance, and I would like to use bitmap and bitmapdata to put the picture on. can you help me out here?

    thank.

    JJ

Login to post your comments. If you do not have an account with us please Register.
Copyright 2005 by ActionScript, Inc.   |  Privacy Statement  |  Terms Of Use  |  ActionScript Client Extranet