Stockage des données d'image pour une application Web hors ligne (base de données de stockage côté client)

105

J'ai une application Web hors ligne utilisant l'appcaching. Je dois lui fournir environ 10 Mo - 20 Mo de données qu'il enregistrera (côté client), principalement des fichiers image PNG. Le fonctionnement est le suivant:

  1. Téléchargements et installations d'applications Web dans appcache (utilise le manifeste)
  2. Demandes d'applications Web à partir de fichiers de données PNG du serveur (comment? - voir les alternatives ci-dessous)
  3. Parfois, l'application Web se resynchronise avec le serveur et effectue de petites mises à jour / suppressions / ajouts partiels à la base de données PNG
  4. Pour info: le serveur est un serveur JSON REST, qui peut placer des fichiers dans wwwroot pour le ramassage

Voici mon analyse actuelle des "bases de données" basées sur le client qui gèrent le stockage d'objets blob binaires

VOIR MISE À JOUR en bas

  • AppCache (via le manifeste, ajoutez tout le PNG, puis mettez à jour à la demande)
    • Inconvénient: tout changement d'un élément de la base de données PNG entraînera le téléchargement complet de tous les éléments du manifeste (vraiment une mauvaise nouvelle!)
  • Espace archivage sur le Web
  • PhoneGap et SQLLite
    • CONTRE: le sponsor la rejettera en tant qu'application native nécessitant une certification
  • fichier zip
    • Le serveur crée un fichier zip, le place dans wwwroot et informe le client
    • l'utilisateur doit décompresser manuellement (du moins c'est ainsi que je le vois) et enregistrer dans le système de fichiers client
    • L'application Web utilise l'API FileSystem pour référencer des fichiers
    • CON: ZIP est peut-être trop volumineux (zip64?), Le temps de création est long
    • CON: Je ne sais pas si l'API FileSystem peut toujours lire hors du bac à sable (je pense que oui)
  • Carte USB ou SD (retour à l'âge de pierre ...)
    • L'utilisateur sera local sur le serveur avant de se déconnecter
    • On pourrait donc lui faire insérer une carte SD, laisser le serveur la remplir de fichiers PNG
    • Ensuite, l'utilisateur le branche sur l'ordinateur portable, la tablette
    • L'application Web utilisera l'API FileSystem pour lire les fichiers
    • CON: Je ne sais pas si l'API FileSystem peut toujours lire hors du bac à sable (je pense que oui)
  • WebSQL
    • Contre: le w3c l'a abandonné (plutôt mauvais)
    • Je pourrais envisager un wrapper Javascript qui utilise IndexedDB et WebSQL comme solution de secours
  • API FileSystem
    • Chrome prend en charge la lecture / écriture des objets blob
    • CON: pas clair sur IE et FireFox (IE10, a msSave non standard)
    • caniuse.com signale la prise en charge d'IOS et d'Android (mais encore une fois, est-ce juste r / w de JSON, ou inclut-il l'API blob complète pour l'écriture?
    • CON: Les gens de FireFox n'aiment pas l'API FileSystem et ne savent pas s'ils prennent en charge la sauvegarde des blobs: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: Beaucoup plus rapide que IndexedDB pour les blobs selon jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (page 2)
  • IndexedDB
    • Bon support dans IE10, FireFox (sauvegarde, lecture des blobs)
    • Bonne vitesse et gestion plus facile qu'un système de fichiers (suppressions, mises à jour)
    • PRO: voir les tests de vitesse: http://jsperf.com/indexeddb-vs-localstorage/15
    • Voir cet article sur le stockage et l'affichage des images dans IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • CON: J'ai confirmé que Chrome ne prend pas encore en charge l'écriture d'objets blob (bogue actuel, mais pas clair quand il sera corrigé)
    • MISE À JOUR: les développeurs Chrome confirment qu'ils y travaillent pour les ordinateurs de bureau et Android! pas encore de calendrier.
  • Encapsuleur JavaScript LawnChair http://brian.io/lawnchair/
    • PRO: wrapper très propre pour IndexedDB, WebSQL ou toute autre base de données que vous avez (pensez polyfill)
    • CON: impossible de stocker des objets blob binaires, uniquement des données: uri (encodage base64) (probablement une faille fatale due au coût de décodage)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb
    • Parashuram a écrit un joli wrapper JQUERY pour l'interface brute IndexedDB
    • PRO: simplifie grandement l'utilisation d'IndexedDB, j'espérais ajouter un shim / polyfill pour Chrome FileSystemAPI
    • CON: il devrait gérer les blobs, mais je n'ai pas pu le faire fonctionner
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google a écrit un PolyFill l'API FileSystem bien testé qui utilise Indexed DB comme solution de secours
    • PRO: l'API FileSystem est bien adaptée pour stocker des objets blob
    • PRO: fonctionne très bien sur FireFox et Chrome
      • PRO: idéal pour la synchronisation avec CouchDB basé sur le cloud
    • CON: pas clair pourquoi, mais cela ne fonctionne pas sur IE10
  • Bibliothèque JavaScript PouchDB http://pouchdb.com/
    • idéal pour synchroniser un CouchDB avec une base de données locale (utilise WebSQL ou IndexedDB (pas mon problème cependant)
    • CON: PAS DE CONTRE, PouchDB prend désormais en charge les blobs binaires pour tous les navigateurs récents (IE, Chrome, Firefox, Chrome sur mobile, etc.) ainsi que de nombreux navigateurs plus anciens. Ce n'était pas le cas lorsque j'ai publié ce post pour la première fois.

REMARQUE: pour voir une donnée: encodage uri de PNG j'ai créé un exemple à: http://jsbin.com/ivefak/1/edit

Fonctionnalités souhaitées / utiles / inédites

  • Aucune application native (EXE, PhoneGap, ObjectiveC, etc.) sur le client (application Web pure)
  • Ne doit fonctionner que sur les derniers Chrome, FireFox, IE10 pour les ordinateurs portables
  • Je souhaite vivement la même solution pour Android Tablet (IOS serait bien aussi) mais n'a besoin que d'un seul navigateur pour fonctionner (FF, Chrome, etc.)
  • Population de base de données initiale rapide
  • EXIGENCE: Récupération très rapide des images par application Web à partir du stockage (DB, fichier)
  • Pas destiné aux consommateurs. Nous pouvons restreindre les navigateurs et demander à l'utilisateur de faire une configuration et des tâches spéciales, mais minimisons cela

Implémentations IndexedDB

  • Il existe un excellent article sur la manière dont IE, FF et Chrome implémentent cela en interne à l' adresse : http://www.aaron-powell.com/web/indexeddb-storage
  • En bref:
    • IE utilise le même format de base de données qu'Exchange et Active Directory pour IndexedDB
    • Firefox utilise SQLite et implémente en quelque sorte une base de données NoSQL dans une base de données SQL
    • Chrome (et WebKit) utilisent un magasin de clés / valeurs qui a un héritage dans BigTable

Mes résultats actuels

  • J'ai choisi d'utiliser une approche IndexedDB (et polyfill avec FileSystemAPI pour Chrome jusqu'à ce qu'ils embarquent le support blob)
  • Pour aller chercher les tuiles, j'ai eu un dilemme car les gens de JQUERY sont impatients d'ajouter ceci à AJAX
  • Je suis allé avec XHR2-Lib de Phil Parsons, qui ressemble beaucoup à JQUERY .ajax () https://github.com/pmp/xhr2-lib
  • Performances pour les téléchargements de 100 Mo (IE10 4s, Chrome 6s, FireFox 7s).
  • Je n'ai pas pu faire fonctionner l'un des wrappers IndexedDB pour les objets blob (pelouse, PouchDB, jquery-indexeddb, etc.)
  • J'ai roulé mon propre wrapper et les performances sont (IE10 2s, Chrome 3s, FireFox 10s)
  • Avec FF, je suppose que nous voyons le problème de performances lié à l'utilisation d'une base de données relationnelle (sqllite) pour un stockage non SQL
  • REMARQUE, Chrome dispose d'outils de débogage exceptionnels (onglet développeur, ressources) pour inspecter l'état de IndexedDB.

Résultats FINAUX publiés ci-dessous comme réponse

Mettre à jour

PouchDB prend désormais en charge les blobs binaires pour tous les navigateurs récents (IE, Chrome, Firefox, Chrome sur mobile, etc.) ainsi que pour de nombreux navigateurs plus anciens. Ce n'était pas le cas lorsque j'ai publié ce post pour la première fois.

DrYSG
la source
1
webstorage ne prend pas en charge json mais les chaînes, vous pouvez donc encoder en base64 votre imagez et les renvoyer en tant que dataurls.
mpm
Ok, mais probablement pas optimal (ou dans les limites du quota) pour 20 Mo d'images, qui sont en fait des tuiles de carte glissantes, qui doivent être récupérées et affichées rapidement par une application de carte LEAFLET lorsque vous zoomez et faites un panoramique.
Dr.YSG
Les recherches que vous avez effectuées sont très utiles.
Bogdan Kulynych
mon point est que vous n'avez pas besoin de traiter des blobs binaires si vous utilisez des images png.
mpm
Vous avez raison, cela vous dérangerait-il que je mette à jour le document pour refléter votre contribution?
Dr.YSG

Réponses:

25

Résultats Cache d'objets blob hors ligne pour les cartes glissantes PNG

Essai

  • 171 fichiers PNG (3,2 Mo au total)
  • Plateformes testées: Chrome v24, FireFox 18, IE 10
  • Devrait également fonctionner avec Chrome et FF pour Android

Récupérer à partir du serveur Web

  • en utilisant XHR2 (pris en charge sur presque tous les navigateurs) pour le téléchargement d'objets blob à partir d'un serveur Web
  • Je suis allé avec XHR2-Lib de Phil Parsons, qui ressemble beaucoup à JQUERY .ajax ()

Espace de rangement

Afficher

  • J'utilise Leaflet http://leafletjs.com/ pour afficher les tuiles de la carte
  • J'ai utilisé le plugin de couche de tuiles fonctionnelle par Ishmael Smyrnow pour récupérer la couche de tuiles de la base de données
  • J'ai comparé la couche de tuiles basée sur la base de données avec un stockage purement local (localhost: //)
  • Il n'y a pas de différence notable de performances! entre l'utilisation d'IndexedDB et des fichiers locaux!

Résultats

  • Chrome: Fetch (6.551s), Store (8.247s), Temps total écoulé: (13.714s)
  • FireFox: Récupérer (0,422 s), Stocker (31,519 s), Temps total écoulé: (32,836 s)
  • IE 10: Récupération (0,668 s), Stockage: (0,896 s), Temps total écoulé: (3,758 s)
DrYSG
la source
4

Pour vos besoins, je suggère que le développement d'un nouveau polyfill basé sur deux autres: FileSystem API to IndexedDB et IndexedDB to WebSQL - est la meilleure option.

Le premier permettra la prise en charge du stockage des objets blob dans Chrome (FileSystem API) et Firefox (IndexedDB), tandis que le second devrait prendre en charge Android et iOS ( WebSQL ). Ce qu'il faut, c'est simplement faire en sorte que ces polyfills fonctionnent ensemble, et je suppose que ce n'est pas difficile.

NB: Comme je n'ai trouvé aucune information à ce sujet sur le Web, vous devriez tester si le stockage de blobs à l'aide du polyfill WebSQL fonctionnera sur iOS et Android. Il semble que cela devrait fonctionner:

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

La source

Bogdan Kulynych
la source
Je me penche vers votre suggestion, mais j'attends les autres. Je n'ai pas d'android à portée de main, mais il serait bon de créer un jsBin ou un jsFiddle et de voir ce qui fonctionne sur Android.
Dr.YSG
1
Ces deux blob sont différents. Sqlite blob est arraybuffer en javascript, tandis que js blob n'a pas d'équivalent dans sqlite. Blob ne peut pas être converti en arraybuffer, bien qu'il puisse être cloné structurellement.
Kyaw Tun
2

J'ai des exemples de mise en cache de carte (exemple ouvert, découvrir des régions et zoomer, basculer hors ligne et les régions découvertes seront disponibles).

Il existe map.js- une couche de carte pour les tuiles hors ligne, storage.js- une implémentation de stockage basée sur IndexedDb et WebSQL (mais cela ne fait que tester l'implémentation avec des performances médiocres).

  • Pour les fichiers de site (html, css, js et etc.), je préfère utiliser le cache d'application.
  • Pour le stockage, je préfère utiliser Indexed DB (support blob), Web SQL (uniquement base64), FileWriter (support blob, mais uniquement chrome). Franchement, le stockage est un gros problème pour cela. Vous avez besoin de la solution de valeur clé la plus rapide qui les mélangera tous. Je pense que c'est une bonne décision d'utiliser la solution existante.
  • Pour récupérer, j'ai utilisé une toile avec CORS. Mais je pense à WebWorkers et XHR2 et cela peut être mieux à la place de canvas car canvas ont des problèmes avec CORS dans différents navigateurs et autres (par exemple, ce titre a été mal stocké dans l'opéra ).

Informations supplémentaires sur les tailles de 2 milliards de villes ( Minsk ):

  • Zoom - 9, tuiles - 2, taille - 52 ko, avec précédente - 52 ko;
  • Zoom - 10, carreaux - 3, taille - 72 ko, avec précédent - 124 ko;
  • Zoom - 11, tuiles - 7, taille - 204 ko, avec précédent - 328 ko;
  • Zoom - 12, carreaux - 17, taille - 348 ko, avec précédent - 676 ​​ko;
  • Zoom - 13, carreaux - 48, taille - 820 ko, avec précédent - 1,5 mb;
  • Zoom - 14, tuiles - 158, taille - 2,2 mb, avec précédent - 3,7 mb;
  • Zoom - 15, tuiles - 586, taille - 5,5 mb, avec précédent - 9,3 mb;
  • Zoom - 16, tuiles - 2264, taille - 15 mb, avec précédent - 24,3 mb;
tbicr
la source
Je suppose que ce sont des tuiles JPG au format glissant EGPS3857, n'est-ce pas? depuis que j'utilise un dépliant et que je fais des superpositions raster, j'ai dû utiliser PNG. consultez également ma démonstration d'utilisation de PouchDB (qui utilise IDB en dessous). stackoverflow.com/questions/16721312/…
Dr.YSG
Oh oui, vous mettez en cache à la volée, mais savez-vous où je peux aller pour obtenir une carte OSM pré-construite (dans le monde entier) pour zoomer 10 ou 11 ou 12? Nous garderions cela sur notre serveur hors ligne.
Dr.YSG
Non, utilisé PNGavec la projection par défaut (EGPS: 3857) mais peu importe JPEGou PNGparce qu'il est utilisé par imgtag ou canvas. Avec mon exemple, vous pouvez simplement précharger les tuiles si vous connaissez les clés des tuiles ( storage.add('x_y_z', 'data:image/png;base64,...')pour chaque tuile stockée), mais vous pouvez toujours les obtenir si vous ne connaissez que les limites (polygone) et les zooms.
tbicr
Je veux m'assurer que nous n'avons pas de problème de langue. Avez-vous un endroit où nous pouvons obtenir un ensemble OSM mondial de tuiles glissantes (PNG ou JPG) pour zoomer au niveau 10?
Dr.YSG
Vous pouvez obtenir un formulaire de tuiles tile.osm.org(rendu mapnik). Par exemple http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Ces tuiles ont un en- Access-Control-Allow-Origin: *tête afin que vous puissiez les obtenir par ajax ou obtenir des données uri (base64) par canvas. Vous pouvez déjà télécharger des tuiles avec votre manifest.json {id: 0-0-0}, mais vous devez vous que vous disposez à droite zoom, x, yséquence.
tbicr
1

Il y a quelques années (pas exactement l'âge de pierre), j'utilisais une applet java signée qui interrogeait son serveur pour les exigences de synchronisation / mise à jour, téléchargerait les fichiers appropriés à partir du serveur et les enregistrait sur le système de fichiers de l'utilisateur (pas une base de données). Cette solution peut fonctionner pour vous, même si vous aurez besoin de quelqu'un pour écrire l'applet et la signer. Pour les solutions de base de données, une telle applet peut utiliser le jdbc disponible pour la plupart des bases de données en utilisant localhost sur un port approprié (par exemple, 3306 pour MySQL). Je crois que la balise applet est obsolète en Html5 mais cela fonctionne toujours. Aucune expérience sur les tablettes Android, je ne peux donc pas commenter cette partie.

Manidip Sengupta
la source
1
J'ai commencé à programmer en FORTRAN en 1968 à l'aide d'un card-punch. Les solutions de l'âge de pierre ne sont donc pas nouvelles pour moi.
Dr.YSG