Menyimpan Data Gambar untuk aplikasi web offline (database penyimpanan sisi klien)

105

Saya memiliki aplikasi web offline menggunakan appcaching. Saya perlu menyediakan sekitar 10MB - 20MB data yang akan disimpan (sisi klien) yang sebagian besar terdiri dari file gambar PNG. Pengoperasiannya adalah sebagai berikut:

  1. Download dan penginstalan aplikasi web di appcache (menggunakan manifes)
  2. Permintaan aplikasi web dari file data server PNG (caranya? - lihat alternatif di bawah)
  3. Terkadang aplikasi web menyinkronkan ulang dengan server, dan melakukan pembaruan / penghapusan / penambahan sebagian kecil ke database PNG
  4. FYI: Server adalah server JSON REST, yang dapat menempatkan file di wwwroot untuk diambil

Berikut adalah analisis saya saat ini tentang "database" berbasis klien yang menangani penyimpanan gumpalan biner

LIHAT UPDATE di Bawah

  • AppCache (melalui manifes tambahkan semua PNG dan kemudian perbarui sesuai permintaan)
    • CON: setiap perubahan item database PNG akan berarti download lengkap semua item dalam manifest (Benar-benar berita buruk!)
  • WebStorage
  • PhoneGap & SQLLite
    • CON: Sponsor akan menolaknya sebagai aplikasi asli yang membutuhkan sertifikasi
  • File ZIP
    • Server membuat file zip, menempatkannya di wwwroot, dan memberi tahu klien
    • pengguna harus secara manual unzip (Setidaknya begitulah yang saya lihat) dan simpan ke sistem file klien
    • Aplikasi web menggunakan API FileSystem untuk mereferensikan file
    • CON: ZIP mungkin terlalu besar (zip64?), Waktu pembuatannya lama
    • CON: Tidak yakin apakah FileSystem API selalu dapat terbaca dari kotak pasir (saya kira begitu)
  • USB atau kartu SD (kembali ke zaman batu ....)
    • Pengguna akan menjadi lokal ke server sebelum offline
    • Jadi kita bisa membuatnya memasukkan kartu SD, biarkan server mengisinya dengan file PNG
    • Kemudian pengguna akan menancapkannya ke laptop, tablet
    • Aplikasi web akan menggunakan API FileSystem untuk membaca file
    • CON: Tidak yakin apakah FileSystem API selalu dapat terbaca dari kotak pasir (saya kira begitu)
  • WebSQL
    • CON: w3c telah meninggalkannya (sangat buruk)
    • Saya mungkin mempertimbangkan pembungkus Javascript yang menggunakan IndexedDB dan WebSQL sebagai fall-back
  • API FileSystem
    • Chrome mendukung baca / tulis blob
    • CON: tidak jelas tentang IE dan FireFox (IE10, memiliki msSave non-standar)
    • caniuse.com melaporkan dukungan IOS dan Android (tapi sekali lagi, apakah ini hanya r / w JSON, atau apakah itu termasuk API blob lengkap untuk menulis?
    • CON: Orang-orang FireFox tidak menyukai API FileSystem & tidak jelas apakah mereka mendukung penyimpanan blob: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: Jauh lebih cepat daripada IndexedDB untuk blob menurut jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (halaman 2)
  • IndexedDB
    • Dukungan yang baik di IE10, FireFox (simpan, baca blob)
    • Kecepatan yang baik dan manajemen yang lebih mudah daripada sistem file (menghapus, memperbarui)
    • PRO: lihat tes kecepatan: http://jsperf.com/indexeddb-vs-localstorage/15
    • Lihat artikel ini tentang menyimpan dan menampilkan gambar di IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • CON: Saya mengonfirmasi bahwa Chrome belum mendukung penulisan blob (bug saat ini, tetapi tidak jelas kapan akan diperbaiki)
    • PEMBARUAN: Pengembang Chrome mengonfirmasi bahwa mereka sedang mengerjakan ini untuk desktop dan android! belum ada garis waktu.
  • LawnChair JavaScript wrapper http://brian.io/lawnchair/
    • PRO: pembungkus yang sangat bersih untuk IndexedDB, WebSQL atau database apa pun yang Anda miliki (pikirkan polyfill)
    • CON: tidak dapat menyimpan gumpalan biner, hanya data: uri (encoding base64) (kemungkinan cacat fatal karena biaya de-encoding)
  • PolyFill JQUERY IndexedDB https://github.com/axemclion/jquery-indexeddb
    • Parashuram telah menulis pembungkus JQUERY yang bagus untuk antarmuka IndexedDB mentah
    • PRO: sangat menyederhanakan menggunakan IndexedDB, saya berharap menambahkan shim / polyfill untuk Chrome FileSystemAPI
    • CON: Seharusnya menangani gumpalan, tetapi saya tidak bisa membuatnya berfungsi
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google telah menulis PolyFill yang teruji dengan baik, FileSystem API yang menggunakan Indexed DB sebagai cadangan
    • PRO: FileSystem API sangat cocok untuk menyimpan blob
    • PRO: berfungsi dengan baik di FireFox dan Chrome
      • PRO: bagus untuk sinkronisasi dengan CouchDB berbasis cloud
    • CON: tidak jelas mengapa, tetapi tidak berfungsi di IE10
  • Pustaka JavaScript PouchDB http://pouchdb.com/
    • bagus untuk menyinkronkan CouchDB dengan DB lokal (menggunakan WebSQL atau IndexedDB (bukan masalah saya)
    • CON: NO CONS, PouchDB sekarang mendukung binary blob untuk semua browser terbaru (IE, Chrome, Firefox, Chrome di ponsel, dll.) Serta banyak browser lama. Itu tidak terjadi ketika saya pertama kali melakukan posting ini.

CATATAN: untuk melihat data: uri encoding PNG Saya buat contoh di: http://jsbin.com/ivefak/1/edit

Fitur Yang Diinginkan / Berguna / Tidak Dibutuhkan

  • Tidak ada aplikasi asli (EXE, PhoneGap, ObjectiveC, dll) di klien (aplikasi web murni)
  • Hanya perlu berjalan di Chrome, FireFox, IE10 terbaru untuk laptop
  • Sangat menginginkan solusi yang sama untuk Tablet Android (IOS juga akan menyenangkan) tetapi hanya perlu satu browser untuk berfungsi (FF, Chrome, dll.)
  • Populasi DB awal yang cepat
  • PERSYARATAN: Pengambilan gambar yang sangat cepat oleh aplikasi web dari penyimpanan (DB, file)
  • Bukan untuk konsumen. Kami dapat membatasi browser, dan meminta pengguna untuk melakukan pengaturan & tugas khusus, tetapi mari kita kurangi itu

Implementasi IndexedDB

  • Ada artikel bagus tentang bagaimana IE, FF, dan Chrome menerapkan ini secara internal di: http://www.aaron-powell.com/web/indexeddb-storage
  • Pendeknya:
    • IE menggunakan format database yang sama dengan Exchange dan Active Directory untuk IndexedDB
    • Firefox menggunakan SQLite sehingga jenis penerapan database NoSQL ke database SQL
    • Chrome (dan WebKit) menggunakan penyimpanan Kunci / Nilai yang memiliki warisan di BigTable

Hasil Saya Saat Ini

  • Saya memilih untuk menggunakan pendekatan IndexedDB (dan polyfill dengan FileSystemAPI untuk Chrome sampai mereka mengirimkan dukungan blob)
  • Untuk mengambil ubin, saya mengalami dilema karena orang-orang JQUERY tertarik untuk menambahkan ini ke AJAX
  • Saya menggunakan XHR2-Lib oleh Phil Parsons, yang sangat mirip dengan JQUERY .ajax () https://github.com/pmp/xhr2-lib
  • Performa untuk unduhan 100MB (IE10 4s, Chrome 6s, FireFox 7s).
  • Saya tidak bisa mendapatkan pembungkus IndexedDB apa pun yang berfungsi untuk blob (kursi taman, PouchDB, jquery-indexeddb, dll.)
  • Saya menggulung pembungkus saya sendiri, dan kinerjanya (IE10 2s, Chrome 3s, FireFox 10s)
  • Dengan FF, saya berasumsi kami melihat masalah kinerja menggunakan DB relasional (sqllite) untuk penyimpanan non-sql
  • CATATAN, Chrome memiliki alat debug yang luar biasa (tab pengembang, sumber daya) untuk memeriksa status IndexedDB.

Hasil AKHIR diposting di bawah ini sebagai jawaban

Memperbarui

PouchDB sekarang mendukung gumpalan biner untuk semua browser terbaru (IE, Chrome, Firefox, Chrome di ponsel, dll.) Serta banyak browser lama. Itu tidak terjadi ketika saya pertama kali melakukan posting ini.

Dr.YSG
sumber
1
webstorage tidak mendukung json tetapi string, jadi Anda bisa base64 menyandikan imagez Anda dan menyajikannya kembali sebagai dataurls.
mpm
Oke, tapi mungkin tidak optimal (atau dalam kuota) untuk citra 20MB, yang sebenarnya adalah petak peta licin, yang perlu diambil & ditampilkan dengan cepat oleh aplikasi peta LEAFLET saat Anda memperbesar dan menggeser.
Dr.YSG
Riset yang Anda lakukan cukup membantu.
Bogdan Kulynych
Maksud saya adalah Anda tidak perlu berurusan dengan gumpalan biner jika Anda menggunakan gambar png.
mpm
Anda benar, maukah Anda jika saya memperbarui dokumen untuk mencerminkan masukan Anda?
Dr.YSG

Jawaban:

25

Hasil cache blob offline untuk peta slippy PNG

Menguji

  • 171 file PNG (total 3,2MB)
  • Platform yang diuji: Chrome v24, FireFox 18, IE 10
  • Juga harus bekerja dengan Chrome & FF untuk Android

Ambil dari server web

  • menggunakan XHR2 (didukung di hampir semua browser) untuk unduhan blob dari server web
  • Saya menggunakan XHR2-Lib oleh Phil Parsons, yang sangat mirip dengan JQUERY .ajax ()

Penyimpanan

Layar

  • Saya menggunakan Leaflet http://leafletjs.com/ untuk menampilkan ubin peta
  • Saya menggunakan plugin lapisan ubin fungsional oleh Ishmael Smyrnow untuk mengambil lapisan ubin dari DB
  • Saya membandingkan lapisan ubin berbasis DB dengan penyimpanan (localhost: //) murni lokal
  • Tidak ada perbedaan performa yang mencolok! antara menggunakan IndexedDB dan file lokal!

Hasil

  • Chrome: Ambil (6.551s), Store (8.247s), Total Waktu Berlalu: (13.714s)
  • FireFox: Ambil (0.422s), Simpan (31.519s), Total Waktu yang Berlalu: (32.836s)
  • IE 10: Ambil (0.668s), Simpan: (0.896s), Total Waktu yang Berlalu: (3.758s)
Dr.YSG
sumber
4

Untuk kebutuhan Anda, saya menyarankan agar mengembangkan polyfill baru berdasarkan dua lainnya: API FileSystem ke IndexedDB dan IndexedDB ke WebSQL - adalah opsi terbaik.

Yang pertama akan mengaktifkan dukungan untuk menyimpan blob di Chrome (FileSystem API) dan Firefox (IndexedDB), sedangkan yang terakhir akan memberikan dukungan untuk Android dan iOS ( WebSQL ). Yang dibutuhkan hanyalah membuat polyfill ini bekerja sama, dan saya kira itu tidak sulit.

NB: Karena saya tidak dapat menemukan informasi apa pun di web tentang ini, Anda harus menguji apakah menyimpan blob menggunakan polyfill WebSQL akan berfungsi di iOS dan Android. Sepertinya itu harus berfungsi:

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

Sumber

Bogdan Kulynych
sumber
Saya bersandar pada saran Anda, tetapi saya menunggu untuk mendengar dari orang lain. Saya tidak memiliki android yang berguna, tetapi alangkah baiknya untuk membuat jsBin atau jsFiddle dan melihat apa yang berfungsi di Android.
Dr.YSG
1
Kedua gumpalan ini berbeda. Blob sqlite adalah arraybuffer dalam javascript, sedangkan blob js tidak ada padanannya di sqlite. Blob tidak dapat mengkonversi ke arraybuffer, meskipun dapat di-clone secara struktural.
Kyaw Tun
2

Saya memiliki contoh cache peta ( contoh terbuka, temukan wilayah dan zoom, beralih offline dan wilayah yang ditemukan akan tersedia).

Ada map.js- lapisan peta untuk ubin offline, storage.js- implementasi penyimpanan berdasarkan IndexedDb dan WebSQL (tetapi ini hanya menguji implementasi dengan kinerja yang buruk).

  • Untuk file situs (html, css, js dan lain-lain) saya lebih suka menggunakan cache aplikasi.
  • Untuk penyimpanan saya lebih suka menggunakan Indexed DB (support blob), Web SQL (hanya base64), FileWriter (mendukung blob, tetapi hanya chrome). Terus terang penyimpanan adalah masalah besar untuk ini. Anda membutuhkan solusi nilai kunci tercepat yang akan mencampur semuanya. Saya pikir adalah keputusan yang baik untuk menggunakan solusi yang ada.
  • Untuk mengambil saya menggunakan kanvas dengan CORS. Tapi saya berpikir tentang WebWorkers dan XHR2 dan ini bisa lebih baik daripada kanvas karena kanvas memiliki masalah dengan CORS di browser yang berbeda dan lainnya (misalnya , judul ini disimpan dengan buruk di opera ).

Informasi tambahan tentang ukuran untuk 2 miliar kota ( Minsk ):

  • Zoom - 9, ubin - 2, ukuran - 52 kb, dengan sebelumnya - 52 kb;
  • Zoom - 10, ubin - 3, ukuran - 72 kb, dengan sebelumnya - 124 kb;
  • Zoom - 11, ubin - 7, ukuran - 204 kb, dengan sebelumnya - 328 kb;
  • Zoom - 12, ubin - 17, ukuran - 348 kb, dengan sebelumnya - 676 ​​kb;
  • Zoom - 13, ubin - 48, ukuran - 820 kb, dengan sebelumnya - 1,5 mb;
  • Zoom - 14, ubin - 158, ukuran - 2,2 mb, dengan sebelumnya - 3,7 mb;
  • Zoom - 15, ubin - 586, ukuran - 5,5 mb, dengan sebelumnya - 9,3 mb;
  • Zoom - 16, ubin - 2264, ukuran - 15 mb, dengan sebelumnya - 24,3 mb;
tbicr
sumber
Saya berasumsi itu adalah ubin JPG dalam format EGPS3857 yang licin, bukan? karena saya menggunakan leaflet dan melakukan ovelay raster, saya harus menggunakan PNG. lihat juga demo saya menggunakan PouchDB (yang menggunakan IDB di bawahnya). stackoverflow.com/questions/16721312/…
Dr.YSG
Oh ya, Anda melakukan cache dengan cepat, tetapi tahukah Anda ke mana saya bisa pergi untuk menurunkan peta OSM (seluruh dunia) yang sudah dibuat sebelumnya untuk memperbesar 10 atau 11 atau 12? Kami akan menyimpan ini di server offline kami.
Dr.YSG
Tidak, digunakan PNGdengan proyeksi default (EGPS: 3857) tetapi tidak masalah JPEGatau PNGkarena digunakan oleh imgtag atau canvas. Dengan contoh saya, Anda dapat melakukan pramuat petak jika Anda mengetahui tombol petak ( storage.add('x_y_z', 'data:image/png;base64,...')untuk setiap petak yang disimpan), tetapi Anda selalu bisa mendapatkannya jika hanya mengetahui batas (poligon) dan zoom.
tbicr
Saya ingin memastikan bahwa kami tidak memiliki masalah bahasa. Apakah Anda ada tempat di mana kami bisa mendapatkan set ubin licin OSM di seluruh dunia (PNG atau JPG) untuk memperbesar level 10?
Dr.YSG
Anda bisa mendapatkan bentuk ubin tile.osm.org(perender mapnik). Misalnya http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Ubin ini memiliki Access-Control-Allow-Origin: *header sehingga Anda bisa mendapatkannya dengan ajax atau mendapatkan data uri (base64) dengan kanvas. Anda sudah dapat men-download ubin dengan Anda manifest.json {id: 0-0-0}, tetapi Anda harus yakin bahwa memiliki hak zoom, x, yurutan.
tbicr
1

Beberapa tahun yang lalu (bukan zaman batu), saya menggunakan applet java bertanda tangan yang akan meminta servernya untuk menyinkronkan / memperbarui persyaratan, mengunduh file yang sesuai dari server dan menyimpannya di sistem file pengguna (bukan database). Solusi itu mungkin berhasil untuk Anda, meskipun Anda akan membutuhkan seseorang untuk menulis applet dan menandatanganinya. Untuk solusi database, applet semacam itu dapat menggunakan jdbc yang tersedia untuk sebagian besar database menggunakan localhost pada port yang sesuai (misalnya, 3306 untuk MySQL). Saya yakin tag applet sudah usang di Html5 tetapi masih berfungsi. Tidak ada pengalaman di tablet Android, jadi tidak bisa mengomentari bagian itu.

Manidip Sengupta
sumber
1
Saya mulai membuat program di FORTRAN pada tahun 1968 dengan menggunakan pukulan kartu. Jadi solusi zaman batu bukanlah hal baru bagi saya.
Dr.YSG