Storing Image Data for offline web application (client-side storage database)

A few years back (not exactly the stone age), I was using a signed java applet that would query its server for syncing/updating requirements, download appropriate files from the server and save them on the user's filesystem (not a database). That solution might work for you, although you will need someone to write the applet and sign it. For database solutions, such an applet can use the jdbc available for most databases using localhost on a suitable port (e.g., 3306 for MySQL). I believe the applet tag is deprecated in Html5 but it still works. No experience on Android tablets, so can't comment on that part.


I have map caching examples(open example, discover regions and zooms, switch offline and discovered regions will availaible).

There are map.js - map layer for offline tiles, storage.js - storage implementation based on IndexedDb and WebSQL (but this just test implementation with poor performance).

  • For site files (html, css, js and etc.) I prefer use application cache.
  • For storage I prefer use Indexed DB (support blob), Web SQL (only base64), FileWriter (support blob, but only chrome). Frankly storage is big issue for this. You need the fastest key value solution that will mix them all. I think is good decision to use exist solution.
  • For fetching I used canvas with CORS. But I thinking about WebWorkers and XHR2 and this can be better instead canvas because canvas have some troubles with CORS in different browsers and other (for example this title was stored bad in opera).

Additional information about sizes for 2 billion city (Minsk):

  • Zoom - 9, tiles - 2, size - 52 kb, with previous - 52 kb;
  • Zoom - 10, tiles - 3, size - 72 kb, with previous - 124 kb;
  • Zoom - 11, tiles - 7, size - 204 kb, with previous - 328 kb;
  • Zoom - 12, tiles - 17, size - 348 kb, with previous - 676 kb;
  • Zoom - 13, tiles - 48, size - 820 kb, with previous - 1.5 mb;
  • Zoom - 14, tiles - 158, size - 2.2 mb, with previous - 3.7 mb;
  • Zoom - 15, tiles - 586, size - 5.5 mb, with previous - 9.3 mb;
  • Zoom - 16, tiles - 2264, size - 15 mb, with previous - 24.3 mb;

Results Offline blob cache for PNG slippy maps

Testing

  • 171 PNG files (total of 3.2MB)
  • Platforms tested: Chrome v24, FireFox 18, IE 10
  • Should also work with Chrome & FF for Android

Fetch from web server

  • using XHR2 (supported on almost all browsers) for blob download from web server
  • I went with XHR2-Lib by Phil Parsons, which is very much like JQUERY .ajax()
    • https://github.com/p-m-p/xhr2-lib

Storage

  • IndexedDB for IE and FireFox
  • Chrome: Polyfill (blob stored using FileSystem API, reference kept in IndexedDB) polyfill
  • A Must read article on "How the browsers store IndexedDB data"
    • http://www.aaron-powell.com/web/indexeddb-storage
  • Note: FireFox uses SQLlite for the NOSQL IndexedDB. That might be the reason for the slow performance. (blobs stored separately)
  • Note: Microsoft IE uses the extensible storage engine:
    • http://en.wikipedia.org/wiki/Extensible_Storage_Engine
  • Note: Chrome uses LevelDB http://code.google.com/p/leveldb/

Display

  • I am using Leaflet http://leafletjs.com/ to show the map tiles
  • I used the functional tile layer plugin by Ishmael Smyrnow for fetching the tile layer from the DB
    • https://github.com/ismyrnow/Leaflet.functionaltilelayer
  • I compared the DB-based tiles layer with a purely local (localhost://) storage
  • There is no noticeable difference in performance! between using IndexedDB and local files!

Results

  • Chrome: Fetch (6.551s), Store (8.247s), Total Elapsed Time: (13.714s)
  • FireFox: Fetch (0.422s), Store (31.519s), Total Elapsed Time: (32.836s)
  • IE 10: Fetch (0.668s), Store: (0.896s), Total Elapsed Time: (3.758s)

For your requirements I suggest that developing a new polyfill based on two others: FileSystem API to IndexedDB and IndexedDB to WebSQL — is the best option.

The former one will enable support for storing blobs in Chrome (FileSystem API) and Firefox (IndexedDB), while the latter should provide the support for Android and iOS (WebSQL). What is needed is just making these polyfills work together, and I suppose it's not hard.

NB: Since I couldn't find any information on the web about this, you should test if storing blobs using the WebSQL polyfill will work on iOS and Android. It looks like it should work though:

var sql = ["CREATE TABLE", idbModules.util.quote(storeName), "(key BLOB", createOptions.autoIncrement ? ", inc INTEGER PRIMARY KEY AUTOINCREMENT" : "PRIMARY KEY", ", value BLOB)"].join(" ")

Source