-
-
Save PrimaryFeather/a08cda0c75ae8ff7a660d76cc391628f to your computer and use it in GitHub Desktop.
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); | |
} | |
} | |
} |
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.
Hi Daniel, nice extension I was thinking to do something like this the other day ;)
I'm thinking of a way to check if the online ressource has been updated or not. Maybe adding a lapsing variable to the local resource is the simple way to do it. After x days, grabbing the latest source and replace the old one.
Obviously it will be better if we could check the online changed file date, but without server code I don't think it's possible...