3

I am trying to get our web app to cache and display images for offline mode, while the storage part is done (default to IndexedDB and fallback to WebSQL for certain device), I am unsure if:

  1. Canvas or XHR is the better option to get image data.

  2. Blob or ArrayBuffer is the better option to store image data.

  3. Whether there are alternatives to these 2 questions I am not aware of.

There are many discussion on stackoverflow surrounding similar topics (Ref 1, 2). But a lot of them were asked in 2012, when FileSystem API was not deprecated and IndexedDB support were not widespread.

It's now 2014. I want to work towards a definitive/best practice answer for IndexedDB storage, with some considerations for WebSQL. Below are my research (as of 2014.09):

For Q1:

  • Canvas method has the advantage of no extra request, but toBlob method is not supported by most browser, conversion between dataUrl and Blob are likely CPU intensive. In addition we will lose image metadata and need to handle cross origin issues.

  • XHR method avoid canvas's drawbacks but introduce an extra request for every image, unless they are already cached by browser. The main advantage being modern browsers with xhr2 support can return binary response as Blob or ArrayBuffer natively.

For Q2:

  • Generally speaking, if you are not working on manipulating binary data, then Blob is the better choice, especially for image caching and display, since you need to call .createObjectURL with Blob anyway.

  • But Chrome has buggy support for Blob type in IndexedDB (fixed in Chrome 38, which is not released yet), and for WebSQL a common solution is to use base64. Both of which suggest ArrayBuffer might be the more compatible choice.

Notes on other potential solutions:

  • localStorage isn't a good fit for content image storage given its 5MB cap. Other problem including synchronous api (blocking IO) and no native support for binary content.

  • appcache would be great for static asset (where resource url are known), but for content image caching they are a headache to manage.

I haven't been able to locate a discussion/article that fully consider compatibility and performance of each choice. Can stackoverflow community help me out?


Update:

For what it's worth, I decide to go with XHR + Blob combination. My main reasoning:

  1. Simplicity: with XHR2 retrieving blob is as easy as setting xhr.responseType = 'blob'

  2. Native: the entire process is based on native api, from XHR Blob, to storing Blob in IndexedDB, to generating Object URL for image display. It might not necessarily imply better performance, but it certainly reduce needs for data conversion in application code.

  3. Design: image caching is not critical to our service, so I decide to support only browser with proper IndexedDB and XHR2.

Community
  • 1
  • 1
bitinn
  • 8,385
  • 8
  • 34
  • 61
  • You mention indexedDB and haven't mentioned plain-old-localStorage. Does that mean you have a large quantity of images and you've eliminated using localStorage to save your images in compressed .jpg format? – markE Sep 19 '14 at 16:03
  • @markE yes, localStorage's 5MB limit won't be enough for my use-case (high resolution content image caching). And given its synchronous api, would be a problem when read/writes are frequent. – bitinn Sep 20 '14 at 05:49
  • What about encoding your image into a dataUrl string using the [fileReader API](http://devdocs.io/dom/filereader.readasdataurl) ? – laurent Sep 23 '14 at 15:15
  • @laurent will not be more efficient than blob or arraybuffer. – bitinn Sep 24 '14 at 12:14

1 Answers1

-1

You seem to be quick to disregard AppCache, that is built exactly for your use case. Yes, the Manifest is not the easiest feature to use, but the functionality is exactly what you need.

You mention that it's hard to manage the Manifest file. But if you can generate a list of files to be stored offline for your custom solution, you can use the same logic to dynamically generate a Manifest file. Just make sure your Manifest file is not a static file, but generated using the server-side language of your choice.

It seems natural to me that reimplementing a big entire feature of a browser will always be trickier than to use something that's built-in, so give AppCache another try. The browser support is also much wider.

Denis
  • 4,251
  • 1
  • 16
  • 20
  • Most of our static content are using appcache to provide offline access. But our manifest is not on the main html as we don't want it to be cached (any page with manifest are automatically cached). I can give numerous reasons why appcache is not fit to the task, but that derail my question. In my experience appcache is anything but "just works", see: http://alistapart.com/article/application-cache-is-a-douchebag – bitinn Sep 25 '14 at 05:01
  • I never said it "just works", I know that it's a complex and annoying feature. You didn't mention in the original question that you have "numerous reasons", thus I figured you should make sure you have really tried the best with built-in browser functionality before you reimplement it from scratch. – Denis Sep 25 '14 at 05:07
  • AppCache should *only* be used for application resource. Here images are app data, should stored in database. – Kyaw Tun Sep 25 '14 at 07:36
  • @Denis AppCache is not designed for dynamic content, you can't invalidate cache item directly, the update-cycle is browser-controlled (thus the backend trickery you need to build dynamic manifest). For what it's worth, storing image in IndexedDB isn't a lot of lines of code, I am just looking for a best approach for extracting data and store them. – bitinn Sep 25 '14 at 07:37