Question

I have an html5 game with a lot, hundreds of mbs, of image assets that I would like to cache using one of the HTML5 storage apis. Generally they are just img elements with the src linked to from a cdn.

I would like to cache those elements locally so that users can access them faster on subsequent visits.

What's the best way to do this?

Filesystem API: Little support and still requires rewriting urls.
Indexdb: Little support and still  requires rewriting urls
appcache: too small
chrome app: ??

What is, for example, runescape doing?

https://www.runescape.com/game?html5=1

Was it helpful?

Solution

As you noted, the File-system API and IndexDB are not widely supported. That said, I think the solution is dependend mostly on your target audience.

Browser Support

IndexedDB is supported by more browsers than the File-System API. and as this article on Firefox's opinion of the File-System API points out, you can perform the same operations of storing files in IndexDB that you'd be able to perform on the File-System API. There are even javascript libraries that implement the File-System API over IndexedDB.

File sizes/Disk Space

With both technologies, you'll have to manage requesting quotas when limits are exceeded.

a quote from IndexedDB Storage Limits via developer.mozilla

There isn't any limit on a single database item's size. However there may be a limit on each IndexedDB database's size. This limit (and the way the user interface will assert it) may vary from one browser to another.

I do not know what the maximum amount of storage is for IndexedDB on all the browsers, it sounds like Firefox itself posts a request confirmation to the user for permission to store more than 50MB - so you can use what's available to the browser. IE10 has Approximately a 250MB limit see here for more on IE10. I Read some posts on a 5MB Quota on Chrome, but I think it follows the rules of Temporary Storage.

With the File-System API you have unlimited available space for the File-System, if you use Persistent Storage(but here you have to make a quota request from the start, so it's similar to the way Firefox does the Quota request). Temporary Storage has an actual limitation depending on the harddrive space available and some other things(Read this for more info on limitations of the File-System Quota)

I can't speak from experience for IndexedDB on very large files.images, but as for the File-System API, it does a marvelous job performance wise with read and write operations for GB worth of files. You can have single BLOB's hundreds of MB in size and partition various segments. That said, it doesn't sound like that is necessary for your game, since your file sizes (individual file sizes that is) are probably not going to exceed double digit MB.

Conclussion

IndexedDB is probably your best option, considering you're making a web-game and to reach more people, you need to use the API's that are usuable by most people.

The following code snippet is from an article specifically on downloading, writing and reading image files from IndexedDB. After reading the article, the idea of URL rewriting doesn't seem all that daunting compared to what it'd be in the File-System API.

// Retrieve the file that was just stored
transaction.objectStore("elephants").get("image").onsuccess = function (event) {
    var imgFile = event.target.result;
    console.log("Got elephant!" + imgFile);

    // Get window.URL object
    var URL = window.URL || window.webkitURL;

    // Create and revoke ObjectURL
    var imgURL = URL.createObjectURL(imgFile);

    // Set img src to ObjectURL
    var imgElephant = document.getElementById("elephant");
    imgElephant.setAttribute("src", imgURL);

    // Revoking ObjectURL
    URL.revokeObjectURL(imgURL);
};

OTHER TIPS

I think the good way is create Chrome App and store it for downloading on your server. You app can use unlimited storage when will be installed to user. More info:

Chrome extensions there are two types of apps you can create – a Packaged App and a Hosted App.

A packaged app is one that you create and can include a limited amount (10MB) of data. This app can then be published (and hosted by) Google on their Chrome App Store.

A hosted app is one that you host on your own servers (and the one that I’ll be discussing here). In this case there is technically no limit to the amount of data that can be included using “traditional” HTML5 offline caching technology. However in practice there is actually a limit of 260MB for your app with a per-resource limit of about 32MB (see this thread on the Chromium discussion group for details). According to the the discussion I was having with the developer, he agreed that these limits are quite low and will be increased in a future release.

...

Note that in manifest.json the key piece to the storage issue is the permissions array, specifically:

"permissions": [
  "unlimitedStorage"
]

This section is what tells Chrome not to limit how much storage is available to your application.

This is the main targets of this article.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top