Хранение данных изображения для автономного веб-приложения (база данных хранилища на стороне клиента)

106

У меня есть автономное веб-приложение, использующее кэширование приложений. Мне нужно предоставить ему около 10–20 МБ данных, которые он будет сохранять (на стороне клиента), состоящих в основном из файлов изображений PNG. Операция следующая:

  1. Веб-приложение загружается и устанавливается в appcache (использует манифест)
  2. Запросы веб-приложений из файлов данных PNG сервера (как? - альтернативные варианты см. Ниже)
  3. Иногда веб-приложение повторно синхронизируется с сервером и выполняет небольшие частичные обновления / удаления / добавления в базу данных PNG.
  4. К вашему сведению: сервер - это сервер JSON REST, который может размещать файлы в wwwroot для получения

Вот мой текущий анализ клиентских "баз данных", которые обрабатывают двоичное хранилище больших двоичных объектов.

СМОТРЕТЬ ОБНОВЛЕНИЕ внизу

  • AppCache (через манифест добавьте все PNG, а затем обновите по запросу)

    • ПРОТИВ: любое изменение элемента базы данных PNG будет означать полную загрузку всех элементов в манифесте (действительно плохие новости!)
  • Веб-хранилище

    • Минусы: разработан для хранения JSON.
    • ПРОТИВ: может хранить капли только с помощью кодировки base64 (вероятно, фатальный недостаток из-за стоимости декодирования)
    • ПРОТИВ: Жесткое ограничение в 5 МБ для веб-хранилища http://htmlui.com/blog/2011-08-23-5-obscure-facts-about-html5-localstorage.html
  • PhoneGap и SQLLite

    • ПРОТИВ: Спонсор отклонит его как нативное приложение, требующее сертификации.
  • ZIP файл

    • Сервер создает zip-файл, помещает его в wwwroot и уведомляет клиента.
    • пользователь должен вручную разархивировать (по крайней мере, так я это вижу) и сохранить в файловой системе клиента
    • Веб-приложение использует API файловой системы для ссылки на файлы
    • ПРОТИВ: ZIP может быть слишком большим (zip64?), Долго создавать
    • ПРОТИВ: Не уверен, что FileSystem API всегда может читать из песочницы (я так думаю)
  • USB или SD карты (обратно в каменный век ....)

    • Пользователь будет локальным для сервера перед отключением
    • Так что мы могли бы попросить его вставить SD-карту, пусть сервер заполнит ее файлами PNG.
    • Затем пользователь подключит его к ноутбуку, планшету.
    • Веб-приложение будет использовать API файловой системы для чтения файлов
    • ПРОТИВ: Не уверен, что FileSystem API всегда может читать из песочницы (я так думаю)
  • WebSQL

    • ПРОТИВ: w3c отказался от него (довольно плохо)
    • Я мог бы рассмотреть оболочку Javascript, которая использует IndexedDB и WebSQL как запасной вариант.
  • FileSystem API

    • Chrome поддерживает чтение / запись BLOB-объектов
    • ПРОТИВ: непонятно про IE и FireFox (IE10, нестандартный msSave)
    • caniuse.com сообщает о поддержке iOS и Android (но, опять же, это просто R / W JSON, или он включает полный API blob для записи?
    • ПРОТИВ: ребятам FireFox не нравится FileSystem API, и они не понимают, поддерживают ли они сохранение больших двоичных объектов: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: намного быстрее, чем IndexedDB для больших двоичных объектов, согласно jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (стр. 2)
  • IndexedDB

    • Хорошая поддержка в IE10, FireFox (сохранение, чтение blobs)
    • Хорошая скорость и более простое управление, чем файловая система (удаление, обновление)
    • PRO: см. Тесты скорости: http://jsperf.com/indexeddb-vs-localstorage/15
    • См. Эту статью о хранении и отображении изображений в IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • ПРОТИВ: Я подтвердил, что Chrome еще не поддерживает запись больших двоичных объектов (текущая ошибка, но не ясно, когда она будет исправлена)
    • ОБНОВЛЕНИЕ: сообщение в блоге от июня 2014 г. предполагает, что Chrome теперь поддерживает капли вIndexedDB
    • ОБНОВЛЕНИЕ: этот caniuse / indexeddb подтверждает: «Chrome 36 и ниже не поддерживает объекты Blob в качестве значений indexedDB.»; предлагая> Chrome36 поддерживает объекты Blob.
  • Оболочка LawnChair JavaScript http://brian.io/lawnchair/

    • PRO: очень чистая оболочка для IndexedDB, WebSQL или любой другой базы данных, которая у вас есть (подумайте о polyfill)
    • ПРОТИВ: не может хранить двоичные капли, только данные: uri (кодировка base64) (вероятно, фатальный недостаток из-за стоимости декодирования)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb

    • Парашурам написал красивую оболочку JQUERY для необработанного интерфейса IndexedDB.
    • PRO: значительно упрощает использование IndexedDB, я надеялся добавить прокладку / полифилл для Chrome FileSystemAPI
    • ПРОТИВ: Он должен обрабатывать капли, но мне не удалось заставить его работать
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api

    • Эрик Бидельман @ Google написал хорошо протестированный PolyFill API FileSystem, который использует индексированную БД в качестве альтернативы.
    • PRO: API файловой системы хорошо подходит для хранения больших двоичных объектов.
    • PRO: отлично работает в FireFox и Chrome
      • PRO: отлично подходит для синхронизации с облачным CouchDB
    • ПРОТИВ: непонятно почему, но он не работает в IE10
  • Библиотека JavaScript PouchDB http://pouchdb.com/

    • отлично подходит для синхронизации CouchDB с локальной БД (использует WebSQL или IndexedDB (хотя это не моя проблема)
    • ПРОТИВ: НЕТ МИНУСОВ, PouchDB теперь поддерживает двоичные капли для всех последних браузеров (IE, Chrome, Firefox, Chrome на мобильных устройствах и т. Д.), А также для многих старых браузеров. Когда я впервые написал этот пост, этого не было.

ПРИМЕЧАНИЕ: чтобы увидеть кодировку data: uri для PNG, я создал пример по адресу: http://jsbin.com/ivefak/1/edit

Желаемые / полезные / ненужные функции

  • Нет собственного приложения (EXE, PhoneGap, ObjectiveC и т. Д.) На клиенте (чистое веб-приложение)
  • Требуется только запускать последние версии Chrome, FireFox, IE10 для ноутбуков.
  • Сильно хочу такое же решение для Android-планшета (IOS тоже было бы неплохо), но для работы нужен только один браузер (FF, Chrome и т. Д.)
  • Быстрое начальное заполнение БД
  • ТРЕБОВАНИЕ: очень быстрое извлечение изображений веб-приложением из хранилища (БД, файла)
  • Не предназначен для потребителей. Мы можем ограничить браузеры и попросить пользователя выполнить специальные настройки и задачи, но давайте минимизируем это

Реализации IndexedDB

  • Есть отличная статья о том, как IE, FF и Chrome внутренне реализуют это по адресу: http://www.aaron-powell.com/web/indexeddb-storage.
  • Коротко:
    • IE использует тот же формат базы данных, что и Exchange и Active Directory для IndexedDB.
    • Firefox использует SQLite, поэтому это своего рода реализация базы данных NoSQL в базе данных SQL.
    • Chrome (и WebKit) используют хранилище ключей / значений, унаследованное от BigTable.

Мои текущие результаты

  • Я решил использовать подход IndexedDB (и polyfill с FileSystemAPI для Chrome, пока они не предоставят поддержку blob)
  • При извлечении плиток у меня возникла дилемма, так как ребята из JQUERY недовольны тем, чтобы добавить это в AJAX.
  • Я выбрал XHR2-Lib Фила Парсонса, который очень похож на JQUERY .ajax () https://github.com/pmp/xhr2-lib
  • Производительность при загрузке 100 МБ (IE10 4s, Chrome 6s, FireFox 7s).
  • Мне не удалось заставить работать ни одну из оболочек IndexedDB для больших двоичных объектов (lawnchair, PouchDB, jquery-indexeddb и т. Д.)
  • Я свернул свою собственную оболочку, и производительность (IE10 2s, Chrome 3s, FireFox 10s)
  • С FF, я полагаю, мы видим проблему производительности при использовании реляционной БД (sqllite) для хранилища, отличного от sql.
  • ПРИМЕЧАНИЕ. В Chrome есть отличные инструменты отладки (вкладка разработчика, ресурсы) для проверки состояния IndexedDB.

ОКОНЧАТЕЛЬНЫЕ результаты опубликованы ниже в качестве ответа

Обновить

PouchDB теперь поддерживает двоичные BLOB-объекты для всех последних браузеров (IE, Chrome, Firefox, Chrome на мобильных устройствах и т. Д.), А также для многих старых браузеров. Когда я впервые написал этот пост, этого не было.

Доктор YSG
источник
1
webstorage поддерживает не json, а строки, поэтому вы можете кодировать base64 свой imagez и возвращать его как dataurls.
mpm
Хорошо, но, вероятно, не оптимально (или в пределах квоты) для 20 МБ изображений, которые на самом деле представляют собой скользкие фрагменты карты, которые необходимо быстро извлекать и отображать приложением карты LEAFLET при масштабировании и панорамировании.
Dr.YSG 01
Проведенное вами исследование весьма полезно.
Богдан Кулинич 01
Я хочу сказать, что вам не нужно иметь дело с двоичными каплями, если вы используете изображения png.
mpm
Вы правы, не возражаете, если я обновлю документ, чтобы отразить ваш вклад?
Dr.YSG 01

Ответы:

25

Результаты Автономный кеш BLOB-объектов для скользких карт PNG

Тестирование

  • 171 файл PNG (всего 3,2 МБ)
  • Проверенные платформы: Chrome v24, FireFox 18, IE 10
  • Также должен работать с Chrome и FF для Android

Получить с веб-сервера

  • использование XHR2 (поддерживается почти во всех браузерах) для загрузки больших двоичных объектов с веб-сервера
  • Я выбрал XHR2-Lib Фила Парсонса, который очень похож на JQUERY .ajax ()

Место хранения

  • IndexedDB для IE и FireFox
  • Chrome: Polyfill (blob-объект, хранящийся с использованием FileSystem API, ссылка хранится в IndexedDB) polyfill
  • Обязательно прочтите статью «Как браузеры хранят данные IndexedDB»
  • Примечание. FireFox использует SQLlite для NOSQL IndexedDB. Это могло быть причиной низкой производительности. (капли хранятся отдельно)
  • Примечание. Microsoft IE использует расширяемый механизм хранения:
  • Примечание. Chrome использует LevelDB http://code.google.com/p/leveldb/.

Дисплей

  • Я использую Leaflet http://leafletjs.com/ для отображения фрагментов карты
  • Я использовал функциональный плагин слоя плитки от Ishmael Smyrnow для получения слоя плитки из БД.
  • Я сравнил слой тайлов на основе БД с чисто локальным (localhost: //) хранилищем
  • Заметной разницы в производительности нет! между использованием IndexedDB и локальных файлов!

Полученные результаты

  • Chrome: выборка (6,551 с), сохранение (8,247 с), общее прошедшее время: (13,714 с)
  • FireFox: выборка (0,422 с), сохранение (31,519 с), общее прошедшее время: (32,836 с)
  • IE 10: выборка (0,668 с), сохранение: (0,896 с), общее прошедшее время: (3,758 с)
Доктор YSG
источник
4

Для ваших требований я предлагаю разработать новый полифилл на основе двух других: API файловой системы для IndexedDB и IndexedDB для WebSQL - лучший вариант.

Первый обеспечит поддержку хранения больших двоичных объектов в Chrome (FileSystem API) и Firefox (IndexedDB), а второй должен обеспечивать поддержку Android и iOS ( WebSQL ). Что нужно, так это заставить эти полифиллы работать вместе, и я полагаю, что это несложно.

NB: Поскольку я не смог найти никакой информации об этом в Интернете, вам следует проверить, будет ли хранение больших двоичных объектов с помощью полифилла WebSQL работать на iOS и Android. Похоже, это должно работать:

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

Источник

Богдан Кулыныч
источник
Я склоняюсь к вашему предложению, но жду ответа от других. У меня нет удобного андроида, но было бы неплохо создать jsBin или jsFiddle и посмотреть, что работает на Android.
Dr.YSG 01
1
Эти две капли разные. Sqlite blob - это буфер массива в javascript, тогда как js blob не имеет эквивалента в sqlite. Blob нельзя преобразовать в буфер массива, хотя его можно структурно клонировать.
Kyaw Tun
2

У меня есть примеры кэширования карт (открытый пример, обнаружение регионов и масштабирование, переключение в автономный режим, и обнаруженные регионы будут доступны).

Есть map.js - слой карты для автономных тайлов, storage.js- реализация хранилища на основе IndexedDb и WebSQL (но это всего лишь тестовая реализация с плохой производительностью).

  • Для файлов сайта (html, css, js и т. Д.) Я предпочитаю использовать кеш приложения.
  • Для хранения я предпочитаю использовать Indexed DB (поддержка blob), Web SQL (только base64), FileWriter (поддержка blob, но только chrome). Честно говоря, хранение - большая проблема для этого. Вам нужно самое быстрое решение типа "ключ-значение", которое объединит их все. Я считаю хорошим решением использовать существующее решение.
  • Для получения я использовал холст с CORS. Но я думаю о WebWorkers и XHR2, и это может быть лучше вместо холста, потому что у холста есть проблемы с CORS в разных браузерах и других (например, этот заголовок плохо хранился в Opera ).

Дополнительная информация о размерах 2-х миллиардного города ( Минск ):

  • Zoom - 9, плитки - 2, размер - 52 кб, с предыдущим - 52 кб;
  • Zoom - 10, плитки - 3, размер - 72 кб, с предыдущим - 124 кб;
  • Zoom - 11, плитки - 7, размер - 204 кб, с предыдущим - 328 кб;
  • Zoom - 12, плитки - 17, размер - 348 кб, с предыдущим - 676 ​​кб;
  • Zoom - 13, плитки - 48, размер - 820 кб, с предыдущим - 1,5 мб;
  • Zoom - 14, плитки - 158, размер - 2,2 мб, с предыдущим - 3,7 мб;
  • Zoom - 15, плитки - 586, размер - 5,5 мб, с предыдущим - 9,3 мб;
  • Zoom - 16, плитки - 2264, размер - 15 мб, с предыдущим - 24,3 мб;
tbicr
источник
Я предполагаю, что это плитки JPG в скользком формате EGPS3857, верно? так как я использую листовку и делаю растровые овелы, мне пришлось использовать PNG. также посмотрите мою демонстрацию использования PouchDB (который использует IDB внизу). stackoverflow.com/questions/16721312/…
Dr.YSG
О да, вы кешируете на лету, но знаете ли вы, где я могу получить предварительно созданную карту OSM (по всему миру) с уменьшением масштаба до 10, 11 или 12? Мы бы оставили это на нашем автономном сервере.
Dr.YSG
Нет, используется PNGс проекционными по умолчанию (EGPS: 3857) , но независимо от того , JPEGили PNGпотому , что она используется imgтег или canvas. В моем примере вы можете просто предварительно загрузить плитки, если знаете ключи плиток ( storage.add('x_y_z', 'data:image/png;base64,...')для каждой сохраненной плитки), но вы всегда можете получить их, если знаете только границы (многоугольник) и масштабирование.
tbicr
Я хочу убедиться, что у нас нет языковых проблем. Есть ли у вас место, где мы можем получить всемирный набор OSM скользких плиток (PNG или JPG) с уровнем масштабирования 10?
Dr.YSG
Вы можете получить форму тайлов tile.osm.org(рендерер mapnik). Например http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Эти плитки имеют Access-Control-Allow-Origin: *заголовок, поэтому вы можете получить их с помощью ajax или получить URI данных (base64) с помощью холста. Вы уже можете скачать плитки с вашим manifest.json {id: 0-0-0}, но вы должны уверены , что есть право zoom, x, yпоследовательность.
tbicr
1

Несколько лет назад (не совсем в каменном веке) я использовал подписанный Java-апплет, который запрашивал у своего сервера требования к синхронизации / обновлению, загружал соответствующие файлы с сервера и сохранял их в файловой системе пользователя (а не в базе данных). Это решение может сработать для вас, хотя вам понадобится кто-нибудь, чтобы написать апплет и подписать его. Для решений для баз данных такой апплет может использовать jdbc, доступный для большинства баз данных, использующих localhost на подходящем порту (например, 3306 для MySQL). Я считаю, что тег апплета устарел в Html5, но он все еще работает. Нет опыта работы с планшетами Android, поэтому не могу комментировать эту часть.

Манидип Сенгупта
источник
1
Я начал программировать на FORTRAN в 1968 году, используя перфоратор. Так что решения каменного века для меня не новость.
Dr.YSG 01