Almacenamiento de datos de imagen para aplicaciones web sin conexión (base de datos de almacenamiento del lado del cliente)


105

Tengo una aplicación web sin conexión que usa appcaching. Necesito proporcionarle entre 10 MB y 20 MB de datos que guardará (del lado del cliente) que consisten principalmente en archivos de imagen PNG. El funcionamiento es el siguiente:

  1. Descargas e instalaciones de aplicaciones web en appcache (usa el manifiesto)
  2. Solicitudes de aplicaciones web desde archivos de datos PNG del servidor (¿cómo? - vea las alternativas a continuación)
  3. Ocasionalmente, la aplicación web se resincroniza con el servidor y realiza pequeñas actualizaciones / eliminaciones / adiciones parciales a la base de datos PNG
  4. FYI: el servidor es un servidor JSON REST, que puede colocar archivos en wwwroot para su recogida

Aquí está mi análisis actual de las "bases de datos" basadas en el cliente que manejan el almacenamiento de blobs binarios

VER ACTUALIZACIÓN en la parte inferior

  • AppCache (a través del manifiesto, agregue todo el PNG y luego actualice a pedido)
    • CONTRA: cualquier cambio de un elemento de la base de datos PNG significará la descarga completa de todos los elementos en el manifiesto (¡realmente malas noticias!)
  • Almacenamiento web
  • PhoneGap y SQLLite
    • CONTRA: el patrocinador la rechazará como una aplicación nativa que requiere certificación
  • archivo zip
    • El servidor crea un archivo zip, lo coloca en wwwroot y notifica al cliente
    • el usuario tiene que descomprimir manualmente (al menos así es como lo veo) y guardar en el sistema de archivos del cliente
    • La aplicación web usa FileSystem API para hacer referencia a archivos
    • CON: ZIP puede ser demasiado grande (zip64?), Mucho tiempo para crear
    • CONTRA: No estoy seguro de si la API de FileSystem siempre puede leer fuera de la caja de arena (eso creo)
  • USB o tarjeta SD (de vuelta a la edad de piedra ...)
    • El usuario será local en el servidor antes de desconectarse.
    • Entonces podríamos hacer que inserte una tarjeta SD, dejar que el servidor la llene con archivos PNG
    • Luego, el usuario lo conectará a la computadora portátil, tableta
    • La aplicación web utilizará la API FileSystem para leer los archivos
    • CONTRA: No estoy seguro de si la API de FileSystem siempre puede leer fuera de la caja de arena (eso creo)
  • WebSQL
    • CON: w3c lo ha abandonado (bastante mal)
    • Podría considerar un contenedor de Javascript que usa IndexedDB y WebSQL como alternativa
  • API FileSystem
    • Chrome admite lectura / escritura de blobs
    • CONTRA: no está claro acerca de IE y FireFox (IE10, tiene msSave no estándar)
    • caniuse.com informa que es compatible con IOS y Android (pero, de nuevo, ¿es esto solo r / w de JSON o incluye la API de blob completa para escribir?
    • CON: A la gente de FireFox no le gusta la API de FileSystem y no está claro si admiten guardar blobs: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: mucho más rápido que IndexedDB para blobs según jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (página 2)
  • IndexedDB
    • Buen soporte en IE10, FireFox (guardar, leer blobs)
    • Buena velocidad y gestión más sencilla que un sistema de archivos (elimina, actualiza)
    • PRO: consulte las pruebas de velocidad: http://jsperf.com/indexeddb-vs-localstorage/15
    • Consulte este artículo sobre el almacenamiento y visualización de imágenes en IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • CON: Confirmé que Chrome aún no admite la escritura de blobs (error actual, pero no está claro cuándo se solucionará)
    • ACTUALIZACIÓN: ¡Los desarrolladores de Chrome confirman que están trabajando en esto tanto para escritorio como para Android! aún no hay una línea de tiempo.
  • Contenedor de JavaScript de LawnChair http://brian.io/lawnchair/
    • PRO: contenedor muy limpio para IndexedDB, WebSQL o cualquier base de datos que tenga (piense en polyfill)
    • CONTRA: no se pueden almacenar blobs binarios, solo datos: uri (codificación base64) (probablemente falla fatal debido al costo de la decodificación)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb
    • Parashuram ha escrito un buen contenedor JQUERY para la interfaz sin procesar de IndexedDB
    • PRO: simplifica enormemente el uso de IndexedDB, esperaba agregar un shim / polyfill para Chrome FileSystemAPI
    • CON: Debería manejar blobs, pero no pude hacer que funcione
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google ha escrito un PolyFill the FileSystem API bien probado que usa Indexed DB como respaldo
    • PRO: FileSystem API es ideal para almacenar blobs
    • PRO: funciona muy bien en FireFox y Chrome
      • PRO: ideal para sincronizar con CouchDB basado en la nube
    • CON: no está claro por qué, pero no funciona en IE10
  • Biblioteca JavaScript de PouchDB http://pouchdb.com/
    • ideal para sincronizar un CouchDB con una base de datos local (usa WebSQL o IndexedDB (aunque no es mi problema)
    • CON: SIN CONTRAS, PouchDB ahora admite blobs binarios para todos los navegadores recientes (IE, Chrome, Firefox, Chrome en dispositivos móviles, etc.), así como para muchos navegadores más antiguos. Ese no fue el caso cuando hice esta publicación por primera vez.

NOTA: para ver una codificación de datos: uri de PNG, creé un ejemplo en: http://jsbin.com/ivefak/1/edit

Funciones deseadas / útiles / innecesarias

  • Sin aplicación nativa (EXE, PhoneGap, ObjectiveC, etc.) en el cliente (aplicación web pura)
  • Solo necesita ejecutarse en los últimos Chrome, FireFox, IE10 para computadoras portátiles
  • Quiero encarecidamente la misma solución para tabletas Android (IOS también sería bueno) pero solo necesita un navegador para funcionar (FF, Chrome, etc.)
  • Población de base de datos inicial rápida
  • REQUISITO: Recuperación muy rápida de imágenes por aplicación web desde el almacenamiento (DB, archivo)
  • No destinado a los consumidores. Podemos restringir los navegadores y pedirle al usuario que realice tareas y configuraciones especiales, pero minimicemos eso

Implementaciones IndexedDB

  • Hay un excelente artículo sobre cómo IE, FF y Chrome implementan esto internamente en: http://www.aaron-powell.com/web/indexeddb-storage
  • En breve:
    • IE usa el mismo formato de base de datos que Exchange y Active Directory para IndexedDB
    • Firefox está usando SQLite, por lo que está implementando una base de datos NoSQL en la base de datos SQL
    • Chrome (y WebKit) están utilizando una tienda Key / Value que tiene herencia en BigTable

Mis resultados actuales

  • Elegí usar un enfoque IndexedDB (y polyfill con FileSystemAPI para Chrome hasta que envíen soporte para blob)
  • Para buscar los mosaicos, tuve un dilema ya que la gente de JQUERY está ansiosa por agregar esto a AJAX
  • Fui con XHR2-Lib de Phil Parsons, que es muy parecido a JQUERY .ajax () https://github.com/pmp/xhr2-lib
  • Rendimiento para descargas de 100 MB (IE10 4s, Chrome 6s, FireFox 7s).
  • No pude hacer que ninguno de los contenedores IndexedDB funcione para blobs (silla de jardín, PouchDB, jquery-indexeddb, etc.)
  • Hice mi propia envoltura y el rendimiento es (IE10 2s, Chrome 3s, FireFox 10s)
  • Con FF, supongo que estamos viendo el problema de rendimiento de usar una base de datos relacional (sqllite) para un almacenamiento que no es SQL.
  • NOTA, Chrome tiene excelentes herramientas de depuración (pestaña de desarrollador, recursos) para inspeccionar el estado de IndexedDB.

Resultados FINALES publicados a continuación como respuesta

Actualizar

PouchDB ahora admite blobs binarios para todos los navegadores recientes (IE, Chrome, Firefox, Chrome en dispositivos móviles, etc.), así como para muchos navegadores más antiguos. Ese no fue el caso cuando hice esta publicación por primera vez.


1
webstorage no es compatible con json sino con cadenas, por lo que puede codificar en base64 su imagez y devolverlas como dataurls.
mpm

De acuerdo, pero probablemente no sea óptimo (o dentro de la cuota) para 20 MB de imágenes, que en realidad son mosaicos de mapas deslizantes, que deben buscarse y mostrarse rápidamente con una aplicación de mapas LEAFLET a medida que hace zoom y se desplaza.
Dr.YSG

La investigación que ha realizado es muy útil.
Bogdan Kulynych

mi punto es que no necesitas lidiar con blobs binarios si estás usando imágenes png.
mpm

Tiene razón, ¿le importaría si actualizo el documento para reflejar su opinión?
Dr.YSG

Respuestas:


25

Resultados Caché de blobs sin conexión para mapas deslizantes PNG

Pruebas

  • 171 archivos PNG (un total de 3,2 MB)
  • Plataformas probadas: Chrome v24, FireFox 18, IE 10
  • También debería funcionar con Chrome y FF para Android

Obtener del servidor web

  • usando XHR2 (compatible con casi todos los navegadores) para la descarga de blobs desde el servidor web
  • Fui con XHR2-Lib de Phil Parsons, que es muy parecido a JQUERY .ajax ()

Almacenamiento

Monitor

  • Estoy usando Leaflet http://leafletjs.com/ para mostrar los mosaicos del mapa
  • Utilicé el complemento de capa de mosaico funcional de Ishmael Smyrnow para obtener la capa de mosaico de la base de datos
  • Comparé la capa de mosaicos basada en DB con un almacenamiento puramente local (localhost: //)
  • ¡No hay una diferencia notable en el rendimiento! entre usar IndexedDB y archivos locales!

Resultados

  • Chrome: recuperación (6.551 s), tienda (8.247 s), tiempo total transcurrido: (13.714 s)
  • FireFox: Obtener (0.422s), Almacenar (31.519s), Tiempo total transcurrido: (32.836s)
  • IE 10: recuperación (0,668 s), almacenamiento: (0,896 s), tiempo total transcurrido: (3,758 s)

4

Para sus requisitos, sugiero que desarrolle un nuevo polyfill basado en otros dos: API FileSystem para IndexedDB e IndexedDB para WebSQL , es la mejor opción.

El primero permitirá el soporte para almacenar blobs en Chrome (FileSystem API) y Firefox (IndexedDB), mientras que el segundo debería proporcionar el soporte para Android e iOS ( WebSQL ). Lo que se necesita es hacer que estos polyfills funcionen juntos, y supongo que no es difícil.

NB: Dado que no pude encontrar ninguna información en la web sobre esto, debe probar si el almacenamiento de blobs con el polyfill de WebSQL funcionará en iOS y Android. Sin embargo, parece que debería funcionar:

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

Fuente


Me inclino hacia tu sugerencia, pero estoy esperando recibir noticias de otros. No tengo un Android a mano, pero sería bueno crear un jsBin o jsFiddle y ver qué funciona en Android.
Dr.YSG

1
Estos dos blob son diferentes. Sqlite blob es arraybuffer en javascript, mientras que js blob no tiene equivalente en sqlite. Blob no se puede convertir en arraybuffer, aunque se puede clonar estructuralmente.
Kyaw Tun

2

Tengo ejemplos de almacenamiento en caché de mapas (ejemplo abierto, descubrir regiones y zooms, desconectar y las regiones descubiertas estarán disponibles).

Hay map.js- capa de mapa para mosaicos fuera de línea, storage.js- implementación de almacenamiento basada en IndexedDb y WebSQL (pero esto solo prueba la implementación con bajo rendimiento).

  • Para los archivos del sitio (html, css, js, etc.) prefiero usar el caché de la aplicación.
  • Para el almacenamiento, prefiero usar Indexed DB (compatible con blob), Web SQL (solo base64), FileWriter (compatible con blob, pero solo Chrome). Francamente, el almacenamiento es un gran problema para esto. Necesita la solución de valor clave más rápida que los combine todos. Creo que es una buena decisión utilizar la solución existente.
  • Para buscar utilicé lienzo con CORS. Pero estoy pensando en WebWorkers y XHR2 y esto puede ser mejor en lugar de canvas porque canvas tiene algunos problemas con CORS en diferentes navegadores y otros (por ejemplo, este título se almacenó mal en Opera ).

Información adicional sobre tamaños para 2 mil millones de ciudades ( Minsk ):

  • Zoom - 9, mosaicos - 2, tamaño - 52 kb, con anterior - 52 kb;
  • Zoom - 10, mosaicos - 3, tamaño - 72 kb, con anterior - 124 kb;
  • Zoom - 11, mosaicos - 7, tamaño - 204 kb, con anterior - 328 kb;
  • Zoom - 12, mosaicos - 17, tamaño - 348 kb, con anterior - 676 ​​kb;
  • Zoom - 13, mosaicos - 48, tamaño - 820 kb, con anterior - 1,5 mb;
  • Zoom - 14, mosaicos - 158, tamaño - 2,2 mb, con anterior - 3,7 mb;
  • Zoom - 15, mosaicos - 586, tamaño - 5.5 mb, con anterior - 9.3 mb;
  • Zoom - 16, mosaicos - 2264, tamaño - 15 mb, con anterior - 24,3 mb;

Supongo que esos son mosaicos JPG en formato EGPS3857 resbaladizo, ¿verdad? ya que estoy usando folletos y haciendo superposiciones ráster, tuve que ir con PNG. también vea mi demostración de uso de PouchDB (que usa IDB debajo). stackoverflow.com/questions/16721312/…
Dr.YSG

Oh, sí, está almacenando en caché sobre la marcha, pero ¿sabe dónde puedo ir para obtener un mapa OSM preconstruido (en todo el mundo) para hacer zoom 10, 11 o 12? Mantendríamos esto en nuestro servidor fuera de línea.
Dr.YSG

No, se usa PNGcon la proyección predeterminada (EGPS: 3857) pero no importa JPEGo PNGporque se usó por imgetiqueta o canvas. Con mi ejemplo, puede precargar mosaicos si conoce las claves de mosaicos ( storage.add('x_y_z', 'data:image/png;base64,...')para cada mosaico almacenado), pero siempre puede obtenerlos si solo conoce los límites (polígono) y los zooms.
tbicr

Quiero asegurarme de que no tengamos problemas con el idioma. ¿Hay algún lugar en el que podamos obtener un conjunto mundial de OSM de mosaicos deslizantes (PNG o JPG) para ampliar el nivel 10?
Dr.YSG

Puede obtener el formulario de mosaicos tile.osm.org(renderizador de mapnik). Por ejemplo http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Estos mosaicos tienen Access-Control-Allow-Origin: *encabezado para que pueda obtenerlos por ajax u obtener datos uri (base64) por lienzo. Ya se puede descargar baldosas con su manifest.json {id: 0-0-0}, pero hay que ver si dispone de la derecha zoom, x, ysecuencia.
tbicr

1

Hace unos años (no exactamente la edad de piedra), estaba usando un subprograma java firmado que consultaba a su servidor los requisitos de sincronización / actualización, descargaba los archivos apropiados del servidor y los guardaba en el sistema de archivos del usuario (no en una base de datos). Esa solución podría funcionar para usted, aunque necesitará que alguien escriba el subprograma y lo firme. Para soluciones de bases de datos, un subprograma de este tipo puede usar el jdbc disponible para la mayoría de las bases de datos usando localhost en un puerto adecuado (por ejemplo, 3306 para MySQL). Creo que la etiqueta del subprograma está obsoleta en Html5, pero aún funciona. No tengo experiencia en tabletas Android, así que no puedo comentar sobre esa parte.


1
Comencé a programar en FORTRAN en 1968 usando un perforador de tarjetas. Así que las soluciones de la edad de piedra no son nuevas para mí.
Dr.YSG
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.