Products
Technologies

Developer resources

Caching Images to disk after first time they are loaded

Avg. Rating 4.5

Problem

One of the challenges with occasionally connected applications is the need for dynamic images. Dynamic images are easy when the application is run while connected to the internet, but will result in broken images, if the machine is not connected.

Solution

To solve this problem, we use an ImageCacheManager, which checks if the file is cached locally first, before trying to load it from the internet. If the local version exists, it is used, other wise, the remote version is loaded and cached

Detailed explanation

First, we implement the ImageCacheManager, which works as a singleton.  Then, any requests for images which should be cached are made by specifying the source through the image cache manager:

<mx:Image        source="{ImageCacheManager.getInstance().getImageByURL('http://i2.cdn.turner.com/cnn/2008/WORLD/americas/08/26/hurricane.gustav/t1home.gustav.map1.noaa.jpg')}"/>

package managers
{
    import flash.filesystem.File;
    import flash.net.URLRequest;
    import flash.net.URLLoader;
    import flash.events.Event;
    import flash.net.URLLoaderDataFormat;
    import flash.utils.Dictionary;
    import flash.filesystem.FileStream;
    import flash.filesystem.FileMode;
    import com.adobe.crypto.MD5;
   
    public class ImageCacheManager
    {
        private static const imageDir:File = File.applicationStorageDirectory.resolvePath("cachedimages/");
        private static var instance:ImageCacheManager;
        private var pendingDictionaryByLoader:Dictionary = new Dictionary();
        private var pendingDictionaryByURL:Dictionary = new Dictionary();
       

        public function ImageCacheManager()
        {
        }

        public static function getInstance():ImageCacheManager
        {
            if (instance == null)
            {
                instance = new ImageCacheManager();
            }

            return instance;
        }

        public function getImageByURL(url:String):String{
           
            var cacheFile:File = new File(imageDir.nativePath +File.separator+ cleanURLString(url));
            if(cacheFile.exists){
                return cacheFile.url;
            } else {
                addImageToCache(url);
                return url;
            }
           
        }

        private  function addImageToCache(url:String):void{
            if(!pendingDictionaryByURL[url]){
                var req:URLRequest = new URLRequest(url);
                var loader:URLLoader = new URLLoader();
                loader.addEventListener(Event.COMPLETE,imageLoadComplete);
                loader.dataFormat = URLLoaderDataFormat.BINARY;
                loader.load(req);
                pendingDictionaryByLoader[loader] = url;
                pendingDictionaryByURL[url] = true;
            }
        }

        private function imageLoadComplete(event:Event):void{
            var loader:URLLoader = event.target as URLLoader;
            var url:String = pendingDictionaryByLoader[loader];
            var cacheFile:File = new File(imageDir.nativePath +File.separator+ cleanURLString(url));
            var stream:FileStream = new FileStream();
            stream.open(cacheFile,FileMode.WRITE);
            stream.writeBytes(loader.data);
            stream.close();
            delete pendingDictionaryByLoader[loader]
            delete pendingDictionaryByURL[url];
        }

        private function cleanURLString(url:String):String{
            var hash:String = MD5.hash(url);
            return hash;
        }
       
    }
}

 Note:  The ImageCacheManager makes use the the MD5 class, which is available in the as3corelib.swc (http://code.google.com/p/as3corelib/).  This is used not for security or obfuscation purposes, but to ensure the name of the file which is written contains only "safe" characters

ImageCacheManager.zip
[This zip file contains the manager, and a test file. You will need to download as3corelib.swc (as mentioned in detailed description) in order to use this.]

+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes