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

IT技术 javascript html web-applications indexeddb leaflet
2021-02-21 22:15:04

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

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

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

见底部更新

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

    • 缺点:PNG 数据库项目的任何更改都意味着完整下载清单中的所有项目(真是个坏消息!)
  • 网络存储

  • PhoneGap 和 SQLLite

    • CON:赞助商将拒绝它作为需要认证的本机应用程序
  • 压缩文件

    • 服务端创建一个zip文件,放在wwwroot中,并通知客户端
    • 用户必须手动解压缩(至少我是这么看的)并保存到客户端文件系统
    • Web 应用程序使用 FileSystem API 来引用文件
    • 缺点:ZIP 可能太大(zip64?),创建时间很长
    • 缺点:不确定 FileSystem API 是否总是可以从沙箱中读出(我认为是)
  • USB 或 SD 卡(回到石器时代......)

    • 用户在脱机之前将位于服务器本地
    • 所以我们可以让他插入一张 SD 卡,让服务器用 PNG 文件填充它
    • 然后用户将其插入笔记本电脑、平板电脑
    • Web 应用程序将使用 FileSystem API 来读取文件
    • 缺点:不确定 FileSystem API 是否总是可以从沙箱中读出(我认为是)
  • 网络SQL

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

  • 索引数据库

    • 对 IE10、FireFox 的良好支持(保存、读取 blob)
    • 与文件系统(删除、更新)相比,速度快且管理更容易
    • PRO:查看速度测试:http : //jsperf.com/indexeddb-vs-localstorage/15
    • 请参阅有关在 IndexedDB 中存储和显示图像的文章:https ://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • 缺点:我确认 Chrome 尚不支持 blob 写入(当前错误,但不清楚何时修复)
    • 更新:2014 年 6 月的一篇博文建议 Chrome 现在支持 blobIndexedDB
    • 更新:此 caniuse/indexeddb确认:“Chrome 36 及以下版本不支持 Blob 对象作为 indexedDB 值。”;建议 >Chrome36 支持 Blob 对象。
  • LawnChair JavaScript 包装器http://brian.io/lawnchair/

    • PRO:非常干净的 IndexedDB、WebSQL 或您拥有的任何数据库的包装器(想想 polyfill)
    • CON:无法存储二进制 blob,只能存储 data:uri(base64 编码)(由于解编码成本,可能是致命缺陷)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb

    • Parashuram 为原始 IndexedDB 接口编写了一个很好的 JQUERY 包装器
    • PRO:大大简化了 IndexedDB 的使用,我希望为 Chrome FileSystemAPI 添加一个 shim/polyfill
    • 缺点:它应该处理斑点,但我无法让它工作
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api

    • Eric Bidelman @ Google 编写了一个经过良好测试的 PolyFill FileSystem API,它使用索引数据库作为后备
    • PRO:FileSystem API 非常适合存储 blob
    • PRO:在 FireFox 和 Chrome 上运行良好
      • PRO:非常适合与基于云的 CouchDB 同步
    • 缺点:不清楚为什么,但它不适用于 IE10
  • PouchDB JavaScript 库http://pouchdb.com/

    • 非常适合将 CouchDB 与本地数据库同步(使用 WebSQL 或 IndexedDB(虽然不是我的问题)
    • 缺点:没有缺点,PouchDB 现在支持所有最新浏览器(IE、Chrome、Firefox、移动版 Chrome 等)以及许多旧浏览器的二进制 blob。当我第一次写这篇文章时,情况并非如此。

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

所需/有用/不需要的功能

  • 客户端上没有原生(EXE、PhoneGap、ObjectiveC 等)应用程序(纯 Web 应用程序)
  • 只需要在最新的 Chrome、FireFox、IE10 笔记本电脑上运行
  • 强烈希望为 Android 平板电脑提供相同的解决方案(IOS 也不错)但只需要一个浏览器即可工作(FF、Chrome 等)
  • 快速初始数据库填充
  • 要求:通过 Web 应用程序从存储(数据库、文件)中非常快速地检索图像
  • 不适合消费者。我们可以限制浏览器,并要求用户做特殊的设置和任务,但让我们尽量减少

IndexedDB 实现

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

我目前的成绩

  • 我选择使用 IndexedDB 方法(并使用 FileSystemAPI for Chrome 进行 polyfill,直到它们提供 blob 支持)
  • 为了获取瓷砖,我遇到了困境,因为 JQUERY 的人正在讨论将其添加到 AJAX
  • 我使用了 Phil Parsons 的 XHR2-Lib,它非常像 JQUERY .ajax() https://github.com/pmp/xhr2-lib
  • 100MB 下载性能(IE10 4s、Chrome 6s、FireFox 7s)。
  • 我无法让任何 IndexedDB 包装器用于 blob(lawnchair、PouchDB、jquery-indexeddb 等)
  • 我推出了自己的包装器,性能是(IE10 2s、Chrome 3s、FireFox 10s)
  • 使用 FF,我假设我们看到了将关系数据库 (sqllite) 用于非 sql 存储的性能问题
  • 注意,Chrome 具有出色的调试工具(开发人员选项卡、资源)用于检查 IndexedDB 的状态。

最终结果作为答案发布在下面

更新

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

4个回答

结果 PNG 滑动地图的离线 blob 缓存

测试

  • 171 个 PNG 文件(共 3.2MB)
  • 测试平台:Chrome v24、FireFox 18、IE 10
  • 还应该与 Chrome 和 FF for Android 一起使用

从网络服务器获取

  • 使用 XHR2(几乎所有浏览器都支持)从 Web 服务器下载 blob
  • 我使用了 Phil Parsons 的 XHR2-Lib,它非常像 JQUERY .ajax()

贮存

展示

结果

  • Chrome:获取(6.551s),存储(8.247s),总经过时间:(13.714s)
  • FireFox:获取(0.422s),存储(31.519s),总运行时间:(32.836s)
  • IE 10:获取(0.668s),存储:(0.896s),总运行时间:(3.758s)

对于您的要求,我建议基于另外两个开发新的 polyfill: FileSystem API 到 IndexedDBIndexedDB 到 WebSQL — 是最好的选择。

前者将支持在 Chrome (FileSystem API) 和 Firefox (IndexedDB) 中存储 blob,而后者应提供对 Android 和 iOS ( WebSQL ) 的支持。所需要的只是让这些 polyfill 协同工作,我想这并不难。

注意:由于我在网络上找不到任何关于此的信息,您应该测试使用 WebSQL polyfill 存储 blob 是否适用于 iOS 和 Android。看起来它应该可以工作:

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

来源

这两个blob是不同的。Sqlite blob 在 javascript 中是 arraybuffer,而 js blob 在 sqlite 中没有等价物。Blob 不能转换为 arraybuffer,尽管它可以在结构上克隆。
2021-04-18 22:15:04
我倾向于你的建议,但我在等待其他人的意见。我没有方便的 android,但最好创建一个 jsBin 或 jsFiddle,看看什么在 Android 上有效。
2021-05-07 22:15:04

我有地图缓存示例(打开示例,发现区域和缩放,离线切换和发现的区域将可用)。

map.js- 离线图块的地图层,storage.js- 基于 IndexedDb 和 WebSQL 的存储实现(但这只是性能不佳的测试实现)。

  • 对于站点文件(html、css、js 等),我更喜欢使用应用程序缓存。
  • 对于存储,我更喜欢使用 Indexed DB(支持 blob)、Web SQL(仅 base64)、FileWriter(支持 blob,但仅支持 chrome)。坦率地说,存储是一个大问题。您需要将它们混合在一起的最快的键值解决方案。我认为使用现有解决方案是个好决定。
  • 为了获取,我使用了带有 CORS 的画布。但是我在考虑 WebWorkers 和 XHR2,这可以更好地代替画布,因为画布在不同浏览器和其他浏览器中的 CORS 存在一些问题(例如,这个标题在 opera中存储不好)。

关于 20 亿城市(明斯克规模的附加信息

  • 缩放 - 9,图块 - 2,大小 - 52 kb,前一个 - 52 kb;
  • 缩放 - 10,图块 - 3,大小 - 72 kb,之前 - 124 kb;
  • 缩放 - 11,图块 - 7,大小 - 204 kb,之前 - 328 kb;
  • 缩放 - 12,图块 - 17,大小 - 348 kb,之前 - 676 kb;
  • 缩放 - 13,图块 - 48,大小 - 820 kb,之前 - 1.5 mb;
  • 缩放 - 14,图块 - 158,大小 - 2.2 mb,前一个 - 3.7 mb;
  • 缩放 - 15,图块 - 586,大小 - 5.5 mb,前一个 - 9.3 mb;
  • 缩放 - 16,图块 - 2264,大小 - 15 mb,前一个 - 24.3 mb;
不,PNG与默认投影 (EGPS:3857) 一起使用,但无论JPEGPNG因为它被img标签或canvas. 在我的示例中,如果您知道图块键(storage.add('x_y_z', 'data:image/png;base64,...')对于每个存储的图块),您可以只预加载图块,但是如果只知道边界(多边形)和缩放,您总是可以获得它们。
2021-04-17 22:15:04
您可以获得瓷砖形式tile.osm.org(mapnik 渲染器)。例如http://tile.openstreetmap.org/10/590/329.pngzoom/ x/ ypng格式)。此磁贴具有Access-Control-Allow-Origin: *标题,因此您可以通过 ajax 获取它们或通过画布获取数据 uri (base64)。您已经可以使用您的 下载图块manifest.json {id: 0-0-0},但您必须确保具有正确的zoomxy序列。
2021-04-17 22:15:04
我假设这些是滑动 EGPS3857 格式的 JPG 瓷砖,对吗?因为我正在使用传单并进行光栅叠加,所以我不得不使用 PNG。还可以查看我使用 PouchDB 的演示(在下面使用 IDB)。stackoverflow.com/questions/16721312/...
2021-05-02 22:15:04
哦,是的,您正在即时缓存,但是您知道我可以去哪里获得预建的 OSM 地图(全球)以放大 10、11 或 12 吗?我们会将其保存在我们的离线服务器上。
2021-05-03 22:15:04
我想确保我们没有语言问题。您有什么地方可以让我们在全球范围内获得一组 OSM 的滑动图块(PNG 或 JPG)以缩放级别 10?
2021-05-04 22:15:04

几年前(不完全是石器时代),我使用了一个签名的 Java 小程序,它会查询其服务器的同步/更新要求,从服务器下载适当的文件并将它们保存在用户的文件系统(不是数据库)上。该解决方案可能对您有用,尽管您需要有人编写小程序并对其进行签名。对于数据库解决方案,这样的小程序可以使用适用于大多数数据库的 jdbc,在合适的端口上使用 localhost(例如,3306 用于 MySQL)。我相信小程序标签在 Html5 中已被弃用,但它仍然有效。没有Android平板电脑的经验,所以不能评论那部分。

我于 1968 年开始使用卡片打孔机在 FORTRAN 中编程。所以石器时代的解决方案对我来说并不陌生。
2021-05-15 22:15:04