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


105

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

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

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

在底部查看更新

  • AppCache(通过清单添加所有PNG,然后按需更新)
    • 缺点:PNG数据库项目的任何更改都意味着完整下载清单中的所有项目(真的是坏消息!)
  • 网络存储
  • PhoneGap和SQLLite
    • 缺点:赞助商将其拒绝为需要认证的本地应用
  • ZIP文件
    • 服务器创建一个zip文件,将其放在wwwroot中,并通知客户端
    • 用户必须手动解压缩(至少我是这样)并将其保存到客户端文件系统
    • Web应用程序使用FileSystem API引用文件
    • 缺点:ZIP可能太大(zip64?),创建时间很长
    • 缺点:不确定FileSystem API是否可以始终从沙箱中读取(我认为是)
  • USB或SD卡(回到石器时代。...)
    • 用户将在离线之前位于服务器本地
    • 这样我们就可以让他插入SD卡,让服务器用PNG文件填充
    • 然后用户将其插入笔记本电脑,平板电脑
    • Web应用程序将使用FileSystem API读取文件
    • 缺点:不确定FileSystem API是否可以始终从沙箱中读取(我认为是)
  • WebSQL
    • 缺点:w3c放弃了它(非常糟糕)
    • 我可能会考虑使用IndexedDB和WebSQL作为后备的Javascript包装器
  • 文件系统API
  • 索引数据库
    • IE10和FireFox的良好支持(保存,读取blob)
    • 比文件系统更好的速度和更轻松的管理(删除,更新)
    • 专业人士:请参阅速度测试:http : //jsperf.com/indexeddb-vs-localstorage/15
    • 请参阅有关在IndexedDB中存储和显示图像的文章:https ://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • 缺点:我确认Chrome浏览器尚不支持Blob写入(当前错误,但尚不清楚何时会修复)
    • 更新:Chrome开发人员确认他们正在针对台式机和Android进行这项工作!尚无时间表。
  • 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添加填充程序/填充
    • 缺点:应该可以处理斑点,但是我无法使其正常工作
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google编写了经过充分测试的PolyFill FileSystem API,该API使用Indexed DB作为回退
    • PRO:FileSystem API非常适合存储Blob
    • PRO:在FireFox和Chrome上运行出色
      • PRO:非常适合与基于云的CouchDB同步
    • CON:不清楚原因,但是在IE10上不起作用
  • PouchDB JavaScript库http://pouchdb.com/
    • 非常适合将CouchDB与本地数据库同步(使用WebSQL或IndexedDB(虽然不是我的问题)
    • 缺点:没有缺点,PouchDB现在为所有最新的浏览器(IE,Chrome,Firefox,移动设备上的Chrome等)以及许多较旧的浏览器都支持二进制blob。当我第一次发表这篇文章时,情况并非如此。

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

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

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

IndexedDB实现

  • 关于IE,FF和Chrome如何在内部实现此功能的文章非常出色,网址为:http : //www.aaron-powell.com/web/indexeddb-storage
  • 简而言之:
    • IE使用与Exchange和Active Directory for IndexedDB相同的数据库格式
    • Firefox使用SQLite,因此在SQL数据库中实现了NoSQL数据库
    • Chrome(和WebKit)正在使用在BigTable中具有传统的键/值存储

我目前的结果

  • 我选择使用IndexedDB方法(并使用适用于Chrome的FileSystemAPI进行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(草地椅,PouchDB,jquery-indexeddb等)
  • 我包装了自己的包装纸,性能为(IE10 2s,Chrome 3s,FireFox 10s)
  • 对于FF,我假设我们正在看到将关系数据库(sqllite)用于非SQL存储的性能问题
  • 注意,Chrome具有出色的调试工具(“开发人员”选项卡,资源),用于检查IndexedDB的状态。

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

更新资料

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


1
webstorage不支持json,但支持string,因此您可以对basez进行base64编码,并将其作为dataurls返回。
mpm

好的,但对于20MB的图像而言可能不是最佳的(或在配额之内),实际上是滑溜的地图图块,需要在缩放和平移时由LEAFLET地图应用程序快速获取和显示。
YSG博士,2013年

您所做的研究非常有帮助。
Bogdan Kulynych

我的意思是,如果您使用的是png图像,则无需处理二进制斑点。
mpm

您是对的,您介意我更新文档以反映您的意见吗?
Dr.YSG

Answers:


25

结果PNG滑动贴图的离线Blob缓存

测试中

  • 171个PNG文件(总计3.2MB)
  • 经过测试的平台:Chrome v24,FireFox 18,IE 10
  • 也应与Android版Chrome&FF一起使用

从网络服务器获取

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

存储

显示

结果

  • 铬:提取(6.551s),存储(8.247s),经过的总时间:(13.714s)
  • FireFox:提取(0.422s),存储(31.519s),总耗用时间:(32.836s)
  • IE 10:提取(0.668s),存储:(0.896s),总耗用时间:(3.758s)

4

根据您的需求,我建议基于其他两个开发新的polyfill: 最好的选择是FileSystem API到IndexedDBIndexedDB到WebSQL

前者将支持在Chrome(FileSystem API)和Firefox(IndexedDB)中存储Blob,而后者应提供对Android和iOS(WebSQL)的支持。需要的只是使这些填充物一起工作,我想这并不难。

注意:由于我在网上找不到与此相关的任何信息,因此您应该测试使用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(" ")

资源


我倾向于您的建议,但我正在等待其他人的来信。我没有方便的android,但是最好创建一个jsBin或jsFiddle并查看在Android上可以使用的方法。
Dr.YSG

1
这两个斑点不同。Sqlite blob在javascript中是arraybuffer,而js blob在sqlite中没有等效项。尽管可以在结构上克隆Blob,但无法将其转换为arraybuffer。
2013年

2

我有地图缓存示例(开放示例,发现区域和缩放,脱机并发现区域可用)。

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

  • 对于站点文件(html,css,js等),我更喜欢使用应用程序缓存。
  • 对于存储,我更喜欢使用索引数据库(支持blob),Web SQL(仅支持base64),FileWriter(支持blob,但仅支持chrome)。坦白地说,存储是一个大问题。您需要将所有这些混合在一起的最快的键值解决方案。我认为使用现有解决方案是一个很好的决定。
  • 为了进行获取,我使用了带有CORS的画布。但是我想到了WebWorkers和XHR2,这可以代替canvas更好,因为canvas在不同的浏览器和其他浏览器中都有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;

我认为这些是草率的EGPS3857格式的JPG瓷砖,对吗?因为我使用传单并做光栅叠加,所以我不得不使用PNG。还可以查看我的使用PouchDB的演示(下面使用IDB)。stackoverflow.com/questions/16721312/…–
Dr.YSG

哦,是的,您正在高速缓存中,但是您知道我可以从哪里获得预先构建的OSM地图(世界范围)以将其缩放10或11或12吗?我们将其保留在我们的离线服务器上。
YSG博士

不,使用PNG默认的投影(EGPS:3857),但不管JPEG还是PNG因为它使用的img标签或canvas。在我的示例中,如果您知道图块键(storage.add('x_y_z', 'data:image/png;base64,...')对于每个存储的图块),则可以仅预加载图块,但只要知道边界(多边形)和缩放,就可以始终加载它们。
tbicr

我想确保我们没有语言问题。您是否可以在任何地方获得全球OSM套滑砖(PNG或JPG)以缩放10级?
YSG博士,

您可以获取图块形式tile.osm.org(mapnik渲染器)。例如http://tile.openstreetmap.org/10/590/329.pngzoom/ x/ y.png)。此图块具有Access-Control-Allow-Origin: *标题,因此您可以通过ajax获取它们,也可以通过画布获取数据uri(base64)。你已经可以下载的瓷砖与你的manifest.json {id: 0-0-0},但你必须确保有权zoomxy序列。
tbicr

1

几年前(不完全是石器时代),我使用的是经过签名的Java小程序,该小程序将查询其服务器的同步/更新要求,从服务器下载适当的文件并将其保存在用户的文件系统(而不是数据库)上。该解决方案可能对您有用,尽管您将需要有人编写小程序并对其进行签名。对于数据库解决方案,这样的applet可以在适当的端口(例如,对于MySQL为3306)上使用localhost使用大多数数据库可用的jdbc。我相信在Html5中不赞成使用applet标签,但仍然可以使用。没有使用Android平板电脑的经验,因此无法对此发表评论。


1
我从1968年开始使用穿孔机在FORTRAN中进行编程。因此,石器时代的解决方案对我而言并不陌生。
YSG博士,2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.