为脱机 Web 应用程序存储图像数据(客户端存储数据库)

我有一个离线 Web 应用程序使用的应用程序。我需要提供它大约10 MB-20 MB 的数据,它将保存(客户端)主要包括 PNG 图像文件。行动如下:

  1. Web 应用程序在 appcache 中下载和安装(使用清单)
  2. 来自服务器 PNG 数据文件的 Web 应用程序请求(如何?-参见下面的备选方案)
  3. 有时 Web 应用程序与服务器重新同步,并对 PNG 数据库进行小的部分更新/删除/添加
  4. 供参考: 服务器是一个 JSON REST 服务器,它可以将文件放在 wwwroot 中以便提取

下面是我目前对处理二进制 blob 存储的基于客户端的“数据库”的分析

请参阅底部更新

  • AppCache (通过清单添加所有 PNG,然后根据需要更新)

    • 反对: 任何 PNG 数据库项目的变化将意味着完全下载所有项目的清单(真的是坏消息!)
  • 网络存储

  • PhoneGap & SQLLite

    • 反对: 赞助商将拒绝它作为一个本地应用程序需要认证
    • 服务器创建一个 zip 文件,将其放在 wwwroot 中,并通知客户端
    • 用户必须手动解压缩(至少在我看来是这样)并保存到客户端文件系统
    • Web 应用程序使用 FileSystemAPI 来引用文件
    • 反对: ZIP 可能太大(zip64?) ,长时间创建
    • 反对: 不确定 FileSystemAPI 是否总能从沙箱中读出(我认为是的)
  • USB 或 SD 卡 (回到石器时代... ...)

    • 用户在脱机之前将是服务器的本地用户
    • 所以我们可以让他插入一张 SD 卡让服务器把 PNG 文件放进去
    • 然后用户将其插入笔记本电脑,平板电脑
    • Web 应用程序将使用 FileSystemAPI 来读取文件
    • 反对: 不确定 FileSystemAPI 是否总能从沙箱中读出(我认为是的)
  • WebSQL

    • 反对: w3c 已经放弃了它(相当糟糕)
    • 我可能会考虑使用 IndexedDB 和 WebSQL 的 Javascript 包装器作为备用
  • 文件系统 API

  • IndexedDB

  • 返回文章 http://brian.io/LawnChair/草坪椅译者:

    • PRO: 对于 IndexedDB、 WebSQL 或者任何你拥有的数据库(比如 polyfill)来说,都是非常干净的包装器
    • CON: 不能存储二进制 blobs,只能存储数据: uri (base64编码)(由于解码成本,可能存在致命缺陷)
  • IndexedDB JQUERY polyFill < a href = “ https://github.com/axemclion/JQUERY-IndexedDB”rel = “ norefrer”> https://github.com/axemclion/JQUERY-IndexedDB

    • Parashuram 为原始 IndexedDB 接口编写了一个很好的 JQUERY 包装器
    • 优点: 极大地简化了 IndexedDB 的使用,我希望为 Chrome FileSystemAPI 添加一个 shim/polyfill
    • 反对: 它应该可以处理气泡,但是我无法让它工作
  • Idb.filesystem.js < a href = “ http://ericbidelman.tumblr.com/post/21649963613/idb-filessystem-js-bring-the-html5-filessystem-api”rel = “ norefrer”> http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api

    • Eric Bidelman@Google 编写了一个测试良好的 PolyFill the FileSystem API,它使用 IndexedDB 作为后备
    • 优点: FileSystemAPI 非常适合存储 blobs
    • 优点: 在 FireFox 和 Chrome 上运行良好
      • 优点: 非常适合与基于云的 CouchDB 进行同步
    • 反对: 不清楚为什么,但它不是在 IE10上工作
  • PouchDB JavaScript 库 < a href = “ http://pochdb.com/”rel = “ norefrer”> http://PouchDB.com/

    • 非常适合将 CouchDB 与本地数据库同步(使用 WebSQL 或 IndexedDB)(但这不是我的问题)
    • 反对: 没有反对意见,PouchDB 现在为所有最近的浏览器(IE,Chrome,Firefox,Chrome 在手机上等等)以及许多旧的浏览器支持二进制 blobs。当我第一次写这篇文章的时候,情况并非如此。

注意: 要查看 PNG 的数据: uri 编码,我在: http://jsbin.com/ivefak/1/edit创建了一个示例

期望/有用/需要的特性

  • 客户端没有本地(EXE,PhoneGap,ObjectiveC 等)应用程序(纯 Web 应用程序)
  • 只需要在最新的 Chrome,FireFox,IE10上运行即可
  • 强烈希望 Android 平板电脑也有同样的解决方案(IOS 也不错) ,但是只需要一个浏览器(FF,Chrome 等等)就可以了
  • 快速初始数据库种群
  • 要求: 通过 Web 应用程序从存储(数据库,文件)非常快速地检索图像
  • 不是给消费者的。我们可以限制浏览器,并要求用户做特殊的设置和任务,但让我们最小化

IndexedDB 实现

  • http://www.aaron-powell.com/web/indexeddb-storage上有一篇关于 IE、 FF 和 Chrome 如何在内部实现这一点的优秀文章
  • 简而言之:
    • IE 对 IndexedDB 使用与 Exchange 和 ActiveDirectory 相同的数据库格式
    • Firefox 正在使用 SQLite,因此在 SQL 数据库中实现了 NoSQL 数据库
    • Chrome (和 WebKit)正在使用一个有 BigTable 传统的 Key/Value 存储

我目前的业绩

  • 我选择使用 IndexedDB 方法(在 Chrome 发布 blob 支持之前使用 FileSystemAPI 填充)
  • 对于获取磁砖,我遇到了一个两难的问题,因为 JQUERY 人员一直在抱怨要把它添加到 AJAX 中
  • 我使用了 Phil Parsons 的 XHR2-Lib,它非常类似于 JQUERY.ajax () https://github.com/p-m-p/xhr2-lib
  • 100MB 下载的性能(IE104s,Chrome6s,FireFox 7s)。
  • 我无法让任何 IndexedDB 包装器为 blobs (lawnhair、 PouchDB、 jquery-IndexedDB 等)工作
  • 我自己做了包装,性能是(IE102s,Chrome3s,FireFox 10s)
  • 对于 FF,我假设我们看到了使用关系数据库(sqlite)作为非 sql 存储的性能问题
  • 注意,Chrome 拥有优秀的调试工具(开发者选项卡,资源)来检查 IndexedDB 的状态。

最终结果如下

更新

PouchDB 现在为所有最新的浏览器(IE,Chrome,Firefox,Chrome 在移动端等)以及许多旧的浏览器支持二进制 blob。当我第一次写这篇文章的时候,情况并非如此。

38350 次浏览

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.

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

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()

Storage

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
  • 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)

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;