Speichern von Bilddaten für Offline-Webanwendungen (clientseitige Speicherdatenbank)


105

Ich habe eine Offline-Webanwendung mit Appcaching. Ich muss ungefähr 10 MB - 20 MB Daten bereitstellen, die gespeichert werden (clientseitig) und hauptsächlich aus PNG-Bilddateien bestehen. Die Operation ist wie folgt:

  1. Webanwendung wird im Appcache heruntergeladen und installiert (verwendet Manifest)
  2. Web-App-Anfragen von Server-PNG-Datendateien (wie? - siehe Alternativen unten)
  3. Gelegentlich wird die Web-App erneut mit dem Server synchronisiert und es werden kleine Teilaktualisierungen / Löschungen / Ergänzungen der PNG-Datenbank durchgeführt
  4. Zu Ihrer Information: Server ist ein JSON-REST-Server, der Dateien zur Abholung in wwwroot ablegen kann

Hier ist meine aktuelle Analyse von clientbasierten "Datenbanken", die den binären Blob-Speicher verwalten

SIEHE UPDATE unten

  • AppCache (über Manifest alle PNG hinzufügen und dann bei Bedarf aktualisieren)
    • CON: Jede Änderung eines PNG-Datenbankelements bedeutet den vollständigen Download aller Elemente im Manifest (Wirklich schlechte Nachrichten!)
  • WebStorage
  • PhoneGap & SQLLite
    • CON: Der Sponsor lehnt es als native App ab, für die eine Zertifizierung erforderlich ist
  • zip-Datei
    • Der Server erstellt eine Zip-Datei, legt sie in wwwroot ab und benachrichtigt den Client
    • Der Benutzer muss manuell entpacken (zumindest sehe ich das so) und im Client-Dateisystem speichern
    • Die Webanwendung verwendet die FileSystem-API, um auf Dateien zu verweisen
    • CON: ZIP ist möglicherweise zu groß (zip64?), Lange Zeit zum Erstellen
    • CON: Ich bin mir nicht sicher, ob die FileSystem-API immer aus der Sandbox lesen kann (ich denke schon).
  • USB- oder SD-Karte (zurück in die Steinzeit ....)
    • Der Benutzer ist lokal auf dem Server, bevor er offline geschaltet wird
    • Wir könnten ihn also eine SD-Karte einlegen lassen und sie vom Server mit PNG-Dateien füllen lassen
    • Dann wird der Benutzer es an den Laptop oder das Tablet anschließen
    • Die Web-App verwendet die FileSystem-API, um die Dateien zu lesen
    • CON: Ich bin mir nicht sicher, ob die FileSystem-API immer aus der Sandbox lesen kann (ich denke schon).
  • WebSQL
    • CON: w3c hat es aufgegeben (ziemlich schlecht)
    • Ich könnte einen Javascript-Wrapper in Betracht ziehen, der IndexedDB und WebSQL als Ersatz verwendet
  • Dateisystem-API
    • Chrome unterstützt das Lesen / Schreiben von Blobs
    • CON: nicht klar über IE und FireFox (IE10, hat nicht standardmäßige msSave)
    • caniuse.com meldet IOS- und Android-Unterstützung (aber ist dies auch nur ein R / W von JSON oder enthält es die vollständige Blob-API zum Schreiben?
    • CON: FireFox-Leute mögen die FileSystem-API nicht und sind sich nicht sicher, ob sie das Speichern von Blobs unterstützen: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: Viel schneller als IndexedDB für Blobs laut jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (Seite 2)
  • IndexedDB
    • Gute Unterstützung in IE10, FireFox (speichern, Blobs lesen)
    • Gute Geschwindigkeit und einfachere Verwaltung als ein Dateisystem (Löschen, Aktualisieren)
    • PRO: siehe Geschwindigkeitstests: http://jsperf.com/indexeddb-vs-localstorage/15
    • Lesen Sie diesen Artikel zum Speichern und Anzeigen von Bildern in IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • CON: Ich habe bestätigt, dass Chrome das Schreiben von Blobs noch nicht unterstützt (aktueller Fehler, aber nicht klar, wann er behoben wird).
    • UPDATE: Chrome-Entwickler bestätigen, dass sie sowohl für Desktop als auch für Android daran arbeiten! Noch keine Zeitleiste.
  • LawnChair JavaScript-Wrapper http://brian.io/lawnchair/
    • PRO: Sehr sauberer Wrapper für IndexedDB, WebSQL oder jede andere Datenbank (denken Sie an Polyfill).
    • CON: Binäre Blobs können nicht gespeichert werden, nur Daten: uri (Base64-Codierung) (wahrscheinlich schwerwiegender Fehler aufgrund der Kosten für die Decodierung)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb
    • Parashuram hat einen schönen JQUERY-Wrapper für die rohe IndexedDB-Schnittstelle geschrieben
    • PRO: Die Verwendung von IndexedDB wird erheblich vereinfacht. Ich hatte gehofft, eine Shim / Polyfill für Chrome FileSystemAPI hinzufügen zu können
    • CON: Es sollte mit Blobs umgehen, aber ich konnte es nicht zum Laufen bringen
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google hat eine gut getestete PolyFill-Dateisystem-API geschrieben, die die indizierte Datenbank als Ersatz verwendet
    • PRO: Die FileSystem API eignet sich gut zum Speichern von Blobs
    • PRO: funktioniert hervorragend unter FireFox und Chrome
      • PRO: ideal für die Synchronisierung mit Cloud-basierter CouchDB
    • CON: nicht klar warum, aber es funktioniert nicht auf IE10
  • PouchDB JavaScript Library http://pouchdb.com/
    • ideal zum Synchronisieren einer CouchDB mit einer lokalen Datenbank (verwendet entweder WebSQL oder IndexedDB (allerdings nicht mein Problem)
    • CON: NO CONS, PouchDB unterstützt jetzt binäre Blobs für alle aktuellen Browser (IE, Chrome, Firefox, Chrome auf Mobilgeräten usw.) sowie viele ältere Browser. Das war nicht der Fall, als ich diesen Beitrag zum ersten Mal schrieb.

HINWEIS: Um eine Daten-Uri-Codierung von PNG anzuzeigen, habe ich ein Beispiel erstellt: http://jsbin.com/ivefak/1/edit

Gewünschte / nützliche / nicht benötigte Funktionen

  • Keine native (EXE, PhoneGap, ObjectiveC usw.) App auf dem Client (reine Webanwendung)
  • Muss nur auf den neuesten Chrome, FireFox, IE10 für Laptops ausgeführt werden
  • Ich möchte unbedingt die gleiche Lösung für Android Tablet (IOS wäre auch nett), brauche aber nur einen Browser (FF, Chrome usw.).
  • Schnelle anfängliche DB-Population
  • ANFORDERUNG: Sehr schnelles Abrufen von Bildern durch eine Webanwendung aus dem Speicher (DB, Datei)
  • Nicht für Verbraucher gedacht. Wir können Browser einschränken und Benutzer bitten, spezielle Einstellungen und Aufgaben vorzunehmen, aber lassen Sie uns das minimieren

IndexedDB-Implementierungen

  • Unter http://www.aaron-powell.com/web/indexeddb-storage finden Sie einen hervorragenden Artikel darüber, wie IE, FF und Chrome dies intern implementieren
  • Zusamenfassend:
    • Der IE verwendet dasselbe Datenbankformat wie Exchange und Active Directory für IndexedDB
    • Firefox verwendet SQLite und implementiert eine Art NoSQL-Datenbank in eine SQL-Datenbank
    • Chrome (und WebKit) verwenden einen Schlüssel- / Wertspeicher, der in BigTable Tradition hat

Meine aktuellen Ergebnisse

  • Ich habe mich für einen IndexedDB-Ansatz entschieden (und Polyfill mit FileSystemAPI für Chrome, bis die Blob-Unterstützung ausgeliefert wird).
  • Um die Kacheln zu holen, hatte ich ein Dilemna, da die JQUERY-Leute darüber nachdenken, dies zu AJAX hinzuzufügen
  • Ich habe mich für XHR2-Lib von Phil Parsons entschieden, was JQUERY .ajax () https://github.com/pmp/xhr2-lib sehr ähnlich ist
  • Leistung für 100 MB Downloads (IE10 4s, Chrome 6s, FireFox 7s).
  • Ich konnte keinen der IndexedDB-Wrapper dazu bringen, für Blobs (Rasenstuhl, PouchDB, jquery-indexeddb usw.) zu arbeiten.
  • Ich habe meinen eigenen Wrapper gerollt und die Leistung ist (IE10 2s, Chrome 3s, FireFox 10s).
  • Ich gehe davon aus, dass bei FF das Leistungsproblem bei der Verwendung einer relationalen Datenbank (SQLite) für einen Nicht-SQL-Speicher auftritt
  • HINWEIS: Chrome verfügt über hervorragende Debug-Tools (Registerkarte "Entwickler", Ressourcen) zur Überprüfung des Status der IndexedDB.

FINAL Ergebnisse unten als Antwort veröffentlicht

Aktualisieren

PouchDB unterstützt jetzt binäre Blobs für alle aktuellen Browser (IE, Chrome, Firefox, Chrome auf Mobilgeräten usw.) sowie für viele ältere Browser. Das war nicht der Fall, als ich diesen Beitrag zum ersten Mal schrieb.


1
webstorage unterstützt nicht json, sondern Zeichenfolgen, sodass Sie Ihr imagez mit base64 codieren und als Dataurls zurückgeben können.
mpm

Ok, aber wahrscheinlich nicht optimal (oder innerhalb des Kontingents) für 20 MB Bilder, bei denen es sich tatsächlich um rutschige Kartenkacheln handelt, die von einer LEAFLET-Kartenanwendung beim Zoomen und Schwenken schnell abgerufen und angezeigt werden müssen.
Dr.YSG

Die Recherche, die Sie durchgeführt haben, ist sehr hilfreich.
Bogdan Kulynych

Mein Punkt ist, dass Sie sich nicht mit binären Blobs befassen müssen, wenn Sie PNG-Bilder verwenden.
mpm

Sie haben Recht, würde es Ihnen etwas ausmachen, wenn ich das Dokument aktualisiere, um Ihre Eingabe widerzuspiegeln?
Dr.YSG

Antworten:


25

Ergebnisse Offline-Blob-Cache für PNG-Slippy-Maps

Testen

  • 171 PNG-Dateien (insgesamt 3,2 MB)
  • Getestete Plattformen: Chrome v24, FireFox 18, IE 10
  • Sollte auch mit Chrome & FF für Android funktionieren

Vom Webserver abrufen

  • Verwenden von XHR2 (wird von fast allen Browsern unterstützt) zum Herunterladen von Blobs vom Webserver
  • Ich habe mich für XHR2-Lib von Phil Parsons entschieden, was JQUERY .ajax () sehr ähnlich ist.

Lager

Anzeige

  • Ich verwende Leaflet http://leafletjs.com/ , um die Kartenkacheln anzuzeigen
  • Ich habe das funktionale Kachelschicht-Plugin von Ishmael Smyrnow verwendet, um die Kachelschicht aus der Datenbank abzurufen
  • Ich habe die DB-basierte Kachelebene mit einem rein lokalen (localhost: //) Speicher verglichen
  • Es gibt keinen merklichen Leistungsunterschied! zwischen der Verwendung von IndexedDB und lokalen Dateien!

Ergebnisse

  • Chrome: Abrufen (6,551 s), Speichern (8,247 s), verstrichene Gesamtzeit: (13,714 s)
  • FireFox: Abrufen (0,422 s), Speichern (31,519 s), verstrichene Gesamtzeit: (32,836 s)
  • IE 10: Abrufen (0,668 s), Speichern: (0,896 s), verstrichene Gesamtzeit: (3,758 s)

4

Für Ihre Anforderungen schlage ich vor, dass die Entwicklung einer neuen Polyfüllung auf der Grundlage von zwei anderen: FileSystem API to IndexedDB und IndexedDB to WebSQL - die beste Option ist.

Ersteres ermöglicht die Unterstützung für das Speichern von Blobs in Chrome (FileSystem API) und Firefox (IndexedDB), während letzteres die Unterstützung für Android und iOS ( WebSQL ) bieten sollte . Was benötigt wird, ist nur, dass diese Polyfills zusammenarbeiten, und ich nehme an, es ist nicht schwer.

NB: Da ich im Web keine Informationen dazu finden konnte, sollten Sie testen, ob das Speichern von Blobs mit der WebSQL-Polyfüllung unter iOS und Android funktioniert. Es sieht so aus, als ob es funktionieren sollte:

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

Quelle


Ich neige zu Ihrem Vorschlag, aber ich warte darauf, von anderen zu hören. Ich habe kein handliches Android, aber es wäre gut, ein jsBin oder jsFiddle zu erstellen und zu sehen, was auf Android funktioniert.
Dr.YSG

1
Diese beiden Blobs sind unterschiedlich. Sqlite-Blob ist Arraybuffer in Javascript, während JS-Blob in SQLite kein Äquivalent hat. Blob kann nicht in Arraybuffer konvertiert werden, obwohl es strukturell geklont werden kann.
Kyaw Tun

2

Ich habe Beispiele für das Zwischenspeichern von Karten (offenes Beispiel, Regionen und Zooms entdecken, offline wechseln und erkannte Regionen sind verfügbar).

Es gibt map.js- Kartenebene für Offline-Kacheln, storage.js- Speicherimplementierung basierend auf IndexedDb und WebSQL (dies testet jedoch nur die Implementierung mit schlechter Leistung).

  • Für Site-Dateien (HTML, CSS, JS usw.) bevorzuge ich die Verwendung des Anwendungscaches.
  • Für die Speicherung bevorzuge ich die indizierte Datenbank (Support-Blob), Web SQL (nur base64) und FileWriter (Support-Blob, aber nur Chrome). Ehrlich gesagt ist Speicherung ein großes Problem dafür. Sie benötigen die schnellste Key-Value-Lösung, die alle miteinander verbindet. Ich denke, es ist eine gute Entscheidung, eine existierende Lösung zu verwenden.
  • Zum Abrufen habe ich Leinwand mit CORS verwendet. Aber ich denke an WebWorkers und XHR2 und dies kann besser sein als Canvas, da Canvas einige Probleme mit CORS in verschiedenen Browsern und anderen hat (zum Beispiel wurde dieser Titel in der Oper schlecht gespeichert ).

Zusätzliche Informationen zu Größen für 2 Milliarden Städte ( Minsk ):

  • Zoom - 9, Kacheln - 2, Größe - 52 kb, mit vorherigen - 52 kb;
  • Zoom - 10, Kacheln - 3, Größe - 72 kb, mit vorherigen - 124 kb;
  • Zoom - 11, Kacheln - 7, Größe - 204 kb, mit vorherigen - 328 kb;
  • Zoom - 12, Kacheln - 17, Größe - 348 kb, mit vorherigen - 676 ​​kb;
  • Zoom - 13, Kacheln - 48, Größe - 820 kb, mit vorherigen - 1,5 mb;
  • Zoom - 14, Kacheln - 158, Größe - 2,2 MB, mit vorherigen - 3,7 MB;
  • Zoom - 15, Kacheln - 586, Größe - 5,5 MB, mit vorherigen - 9,3 MB;
  • Zoom - 16, Kacheln - 2264, Größe - 15 MB, mit vorherigen - 24,3 MB;

Ich nehme an, das sind JPG-Kacheln im rutschigen EGPS3857-Format, oder? Da ich eine Broschüre benutze und Raster-Ovelays mache, musste ich mich für PNG entscheiden. Schauen Sie sich auch meine Demo zur Verwendung von PouchDB an (die IDB darunter verwendet). stackoverflow.com/questions/16721312/…
Dr.YSG

Oh ja, Sie werden im laufenden Betrieb zwischengespeichert, aber wissen Sie, wo ich eine vorgefertigte OSM-Karte (weltweit) abrufen kann, um 10, 11 oder 12 zu zoomen? Wir würden dies auf unserem Offline-Server behalten.
Dr.YSG

Nein, wird PNGmit Standardprojektion (EGPS: 3857) verwendet, aber egal JPEGoder PNGweil es von imgTag oder verwendet wird canvas. In meinem Beispiel können Sie Kacheln nur vorladen, wenn Sie Kachelschlüssel kennen ( storage.add('x_y_z', 'data:image/png;base64,...')für jede gespeicherte Kachel), aber Sie können sie immer erhalten, wenn Sie nur Grenzen (Polygon) und Zooms kennen.
tbicr

Ich möchte sicherstellen, dass wir kein Sprachproblem haben. Haben Sie einen Ort, an dem wir einen weltweiten OSM-Satz rutschiger Kacheln (PNG oder JPG) auf Zoomstufe 10 bringen können?
Dr.YSG

Sie können Kacheln Formular tile.osm.org(Mapnik Renderer) erhalten. Zum Beispiel http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Diese Kacheln haben eine Access-Control-Allow-Origin: *Kopfzeile, sodass Sie sie per Ajax oder Daten-Uri (base64) per Canvas abrufen können. Sie können bereits herunterladen Fliesen mit manifest.json {id: 0-0-0}, aber Sie müssen sicher , dass Recht haben zoom, x, ySequenz.
tbicr

1

Vor ein paar Jahren (nicht gerade in der Steinzeit) verwendete ich ein signiertes Java-Applet, das seinen Server nach Synchronisierungs- / Aktualisierungsanforderungen abfragte, entsprechende Dateien vom Server herunterlud und sie im Dateisystem des Benutzers (keine Datenbank) speicherte. Diese Lösung funktioniert möglicherweise für Sie, obwohl Sie jemanden benötigen, der das Applet schreibt und signiert. Für Datenbanklösungen kann ein solches Applet den für die meisten Datenbanken verfügbaren jdbc verwenden, indem localhost an einem geeigneten Port verwendet wird (z. B. 3306 für MySQL). Ich glaube, das Applet-Tag ist in HTML5 veraltet, aber es funktioniert immer noch. Keine Erfahrung mit Android-Tablets, daher kann ich diesen Teil nicht kommentieren.


1
Ich begann 1968 in FORTRAN mit einem Kartenstempel zu programmieren. Steinzeitlösungen sind für mich also nicht neu.
Dr.YSG
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.