J'ai une application web hors ligne qui utilise appcaching. J'ai besoin de lui fournir environ 10 à 20 Mo de données à sauvegarder (côté client), principalement des fichiers d'images PNG. Le fonctionnement est le suivant :
- L'application web télécharge et installe dans appcache (utilise le manifeste)
- L'application web demande au serveur des fichiers de données PNG (comment ? - voir les alternatives ci-dessous)
- Occasionnellement, l'application web se resynchronise avec le serveur et effectue de petites mises à jour/suppressions/ajouts partiels dans la base de données PNG.
- FYI : Le serveur est un serveur JSON REST, qui peut placer des fichiers dans le wwwroot pour la collecte.
Voici mon analyse actuelle des "bases de données" basées sur le client qui gèrent le stockage de blobs binaires.
VOIR LA MISE À JOUR en bas de page
-
AppCache (via manifeste ajouter tous les PNG et ensuite mettre à jour à la demande)
- CON : toute modification 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 (très mauvaise nouvelle !).
-
WebStorage
- CON : Conçu pour le stockage JSON
- CON : ne peut stocker les blobs que via un encodage base64 (probablement un défaut fatal dû au coût du désencodage)
- CON : Limite stricte de 5MB pour le webStorage http://htmlui.com/blog/2011-08-23-5-obscure-facts-about-html5-localstorage.html
-
PhoneGap & SQLLite
- CON : le sponsor la rejettera comme une application native nécessitant une certification
-
Fichier ZIP
- Le serveur crée un fichier zip, le place dans le répertoire wwwroot, et informe le client.
- l'utilisateur doit dézipper manuellement (du moins c'est comme ça que je le vois) et sauvegarder sur le système de fichiers du client.
- L'application Web utilise l'API FileSystem pour référencer les fichiers.
- CON : ZIP peut être trop grand (zip64 ?), temps de création long
- CON : Pas sûr que l'API FileSystem puisse toujours lire en dehors du bac à sable (je pense que oui)
-
USB ou carte SD (retour à l'âge de pierre....)
- L'utilisateur sera localisé sur le serveur avant d'être mis hors ligne.
- On pourrait lui demander d'insérer une carte SD et laisser le serveur la remplir de fichiers PNG.
- Ensuite, l'utilisateur le branchera sur l'ordinateur portable, la tablette
- L'application Web utilisera l'API FileSystem pour lire les fichiers.
- CON : Pas sûr que l'API FileSystem puisse toujours lire en dehors du bac à sable (je pense que oui)
-
WebSQL
- CON : le w3c l'a abandonné (plutôt mauvais)
- Je pourrais envisager un wrapper Javascript qui utilise IndexedDB et WebSQL comme solution de repli.
-
API pour les systèmes de fichiers
- Chrome prend en charge la lecture/écriture de blobs
- CON : pas clair pour IE et FireFox (IE10, a msSave non standard)
- caniuse.com fait état d'une prise en charge d'IOS et d'Android (mais, là encore, s'agit-il simplement d'un 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 du système de fichiers et ne savent pas s'ils prennent en charge l'enregistrement des blobs : https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
- PRO : Much 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 de blob (bug actuel, mais on ne sait pas quand il sera corrigé)
- MISE À JOUR : les développeurs de Chrome confirment qu'ils travaillent sur ce projet à la fois pour les ordinateurs de bureau et pour Android, mais pas encore de calendrier.
-
Chaise à gazon wrapper JavaScript http://brian.io/lawnchair/
- PRO : enveloppe très propre pour IndexedDB, WebSQL ou toute autre base de données que vous avez (pensez au polyfill).
- CON : ne peut pas stocker de blobs binaires, seulement data:uri (encodage base64) (probablement un défaut fatal dû au coût du désencodage)
-
IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb
- Parashuram a écrit un joli wrapper JQUERY pour l'interface brute d'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 réussi à 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 the FileSystem API bien testé qui utilise Indexed DB comme solution de repli.
- PRO : L'API du système de fichiers est bien adaptée au stockage des blobs.
- PRO : fonctionne parfaitement sur FireFox et Chrome
- PRO : excellent pour la synchronisation avec CouchDB basé sur le cloud
- CON : pas de raison claire, mais cela ne fonctionne pas sur IE10
-
PouchDB Bibliothèque JavaScript http://pouchdb.com/
- idéal pour synchroniser une base de données CouchDB avec une base de données locale (qui utilise soit WebSQL, soit IndexedDB, mais ce n'est pas mon problème).
- CON : PAS DE CONS, PouchDB supporte maintenant 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 fait ce post pour la première fois.
NOTE : pour voir un encodage data:uri de PNG, j'ai créé un exemple à l'adresse suivante : http://jsbin.com/ivefak/1/edit
Caractéristiques souhaitées/utiles/non nécessaires
- Pas d'application native (EXE, PhoneGap, ObjectiveC, etc.) sur le client (application web pure).
- Il suffit d'utiliser les dernières versions de Chrome, FireFox et IE10 pour les ordinateurs portables.
- Je souhaite vivement que la même solution soit appliquée à la tablette Android (IOS serait bien aussi), mais il faut qu'un seul navigateur fonctionne (FF, Chrome, etc.).
- Population initiale rapide des BD
- REQUIS : Récupération très rapide des images par l'application web à partir du stockage (BD, fichier).
- Non 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 mettent en œuvre cette fonctionnalité en interne : 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, ce qui revient à implémenter une base de données NoSQL dans une base de données SQL.
- Chrome (et WebKit) utilise un magasin de clés/valeurs dont l'héritage se trouve dans BigTable.
Mes résultats actuels
- J'ai choisi d'utiliser une approche IndexedDB (et un polyfill avec FileSystemAPI pour Chrome jusqu'à ce qu'ils livrent le support des blobs).
- Pour récupérer les tuiles, j'ai eu un dilemme puisque les gens de JQUERY se plaignent de l'ajout de cette fonctionnalité à AJAX.
- J'ai choisi XHR2-Lib de Phil Parsons, qui ressemble beaucoup à JQUERY .ajax(). https://github.com/p-m-p/xhr2-lib
- Performances pour des téléchargements de 100 Mo (IE10 4s, Chrome 6s, FireFox 7s).
- Je n'ai pu faire fonctionner aucun des wrappers IndexedDB pour les blobs (lawnchair, PouchDB, jquery-indexeddb, etc.).
- J'ai créé mon propre wrapper, et les performances sont les suivantes (IE10 2s, Chrome 3s, FireFox 10s)
- Avec FF, je suppose que nous rencontrons le problème de performance lié à l'utilisation d'une base de données relationnelle (sqllite) pour un stockage non relationnel.
- REMARQUE : Chrome dispose d'outils de débogage exceptionnels (onglet "développeur", ressources) pour inspecter l'état de l'IndexedDB.
Résultats FINAUX affichés ci-dessous comme réponse
Mise à jour
PouchDB supporte désormais 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 fait ce post pour la première fois.