Last active
August 7, 2018 08:29
-
-
Save PrimaryFeather/a08cda0c75ae8ff7a660d76cc391628f to your computer and use it in GitHub Desktop.
A custom DataLoader extension that makes the asset manager cache remote files locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package starling.extensions | |
{ | |
import flash.events.Event; | |
import flash.events.IOErrorEvent; | |
import flash.filesystem.File; | |
import flash.filesystem.FileMode; | |
import flash.filesystem.FileStream; | |
import flash.utils.ByteArray; | |
import starling.assets.DataLoader; | |
public class CachingDataLoader extends DataLoader | |
{ | |
private var _cacheDir:String; | |
public function CachingDataLoader(cacheDirName:String="starling-asset-cache") | |
{ | |
_cacheDir = cacheDirName; | |
} | |
override public function load(url:String, onComplete:Function, | |
onError:Function, onProgress:Function = null):void | |
{ | |
var cacheFile:File; | |
var stream:FileStream; | |
var remoteData:ByteArray; | |
if (url.indexOf("http") == 0) | |
{ | |
cacheFile = getCacheFile(url); | |
if (cacheFile.exists) | |
{ | |
trace("loading from local cache file: " + cacheFile.nativePath); | |
super.load(cacheFile.url, onComplete, onError, onProgress); | |
} | |
else | |
super.load(url, onLoadComplete, onError, onProgress); | |
} | |
else | |
super.load(url, onComplete, onError, onProgress); | |
function onLoadComplete(data:ByteArray):void | |
{ | |
trace("saving to local cache file: " + cacheFile.nativePath); | |
remoteData = data; | |
stream = new FileStream(); | |
stream.addEventListener(Event.CLOSE, onFileStreamClosed); | |
stream.addEventListener(IOErrorEvent.IO_ERROR, onFileStreamError); | |
stream.openAsync(cacheFile, FileMode.WRITE); | |
stream.writeBytes(data); | |
stream.close(); | |
} | |
function onFileStreamClosed(event:Event):void | |
{ | |
cleanup(); | |
onComplete(remoteData); | |
} | |
function onFileStreamError(error:IOErrorEvent):void | |
{ | |
trace("error writing asset store cache: " + error.text); | |
cleanup(); | |
try { stream.close(); } catch (e:Error) {} | |
try { cacheFile.deleteFile(); } catch (e:Error) {} | |
onComplete(remoteData); | |
} | |
function cleanup():void | |
{ | |
stream.removeEventListener(Event.CLOSE, onFileStreamClosed); | |
stream.removeEventListener(IOErrorEvent.IO_ERROR, onFileStreamError); | |
} | |
} | |
private function getCacheFile(remoteUrl:String):File | |
{ | |
var filename:String = hashString(remoteUrl); | |
filename = filename.replace("+", "-").replace("/", "_").replace("=", ""); | |
return File.cacheDirectory.resolvePath(_cacheDir + "/" + filename); | |
} | |
// -> http://www.cse.yorku.ca/%7Eoz/hash.html | |
private static function hashString(str:String):String | |
{ | |
var hash:uint = 5381; | |
for (var i:int = 0, len:int = str.length; i < len; ++i) | |
hash = (hash * 33) ^ str.charCodeAt(i); | |
return hash.toString(16); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @alamboley — sorry, I didn't see your comment sooner!
One simple way to force reloading after a while is to append something like
?version=1
to the resource. That will create a different hash, and so a different name for the cache file. One could simply use the current week number (since, say, 2018/01/01) instead of the version, and so would get a refreshed resource once a week.To let the server signal that the version has actually changed, it would have to signal the file version in the response header. In Flox, we used the "etag" flag to signal a changed version, i.e. the client would remember the version it has downloaded (i.e. store the "etag" from the last download of the resource) and pass it to the server in the request header; if the version is still the same, the server would reply with Http status "NOT_MODIFIED" (304).
That was a custom implementation, though — I don't know if web servers can be configured like that. Though one would think that there should be such a mechanism; after all, browsers need to check file versions, too.