Armazenamento de dados de imagem para aplicativo da web offline (banco de dados de armazenamento do lado do cliente)


105

Eu tenho um aplicativo da web offline usando appcaching. Preciso fornecer cerca de 10 MB a 20 MB de dados que ele salvará (do lado do cliente) consistindo principalmente de arquivos de imagem PNG. A operação é a seguinte:

  1. Download e instalação de aplicativos da Web em appcache (usa manifesto)
  2. Solicitações de aplicativos da web de arquivos de dados PNG do servidor (como? - veja alternativas abaixo)
  3. Ocasionalmente, o aplicativo da web é sincronizado novamente com o servidor e faz pequenas atualizações / exclusões / adições parciais ao banco de dados PNG
  4. FYI: Server é um servidor JSON REST, que pode colocar arquivos em wwwroot para coleta

Aqui está minha análise atual de "bancos de dados" baseados em cliente que lidam com armazenamento de blob binários

VER ATUALIZAÇÃO na parte inferior

  • AppCache (por meio de manifesto, adicione todos os PNG e, em seguida, atualize sob demanda)
    • CON: qualquer alteração de um item do banco de dados PNG significará o download completo de todos os itens no manifesto (notícias realmente ruins!)
  • Armazenamento web
  • PhoneGap e SQLLite
    • CON: O patrocinador irá rejeitá-lo como um aplicativo nativo que requer certificação
  • Arquivo zip
    • O servidor cria um arquivo zip, coloca-o em wwwroot e notifica o cliente
    • o usuário tem que descompactar manualmente (pelo menos é assim que eu vejo) e salvar no sistema de arquivos do cliente
    • O aplicativo da Web usa a API FileSystem para fazer referência a arquivos
    • CON: ZIP pode ser muito grande (zip64?), Muito tempo para criar
    • CON: Não tenho certeza se a API FileSystem sempre pode ler do sandbox (acho que sim)
  • USB ou cartão SD (de volta à idade da pedra ....)
    • O usuário estará local no servidor antes de ficar offline
    • Então, poderíamos fazer com que ele insira um cartão SD, deixe o servidor preenchê-lo com arquivos PNG
    • Em seguida, o usuário irá conectá-lo ao laptop, tablet
    • O aplicativo da Web usará a API FileSystem para ler os arquivos
    • CON: Não tenho certeza se a API FileSystem sempre pode ler do sandbox (acho que sim)
  • WebSQL
    • CON: w3c abandonou (muito ruim)
    • Eu posso considerar um wrapper Javascript que usa IndexedDB e WebSQL como uma alternativa
  • API FileSystem
    • Chrome suporta leitura / gravação de blobs
    • CON: não está claro sobre IE e FireFox (IE10, tem msSave não padrão)
    • caniuse.com relata suporte a IOS e Android (mas, novamente, isso é apenas r / w de JSON ou inclui a API de blob completa para gravação?
    • CON: o pessoal do FireFox não gosta da API FileSystem e não está claro se eles oferecem suporte para salvar blobs: https://hacks.mozilla.org/2012/07/why-no-filesystem-api-in-firefox/
    • PRO: muito mais rápido do que IndexedDB para blobs de acordo com jsperf http://jsperf.com/indexeddb-vs-localstorage/15 (página 2)
  • IndexedDB
    • Bom suporte no IE10, FireFox (salvar, ler blobs)
    • Boa velocidade e gerenciamento mais fácil do que um sistema de arquivos (exclusões, atualizações)
    • PRO: veja os testes de velocidade: http://jsperf.com/indexeddb-vs-localstorage/15
    • Veja este artigo sobre armazenamento e exibição de imagens em IndexedDB: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
    • CON: Confirmei que o Chrome ainda não oferece suporte à escrita de blob (bug atual, mas não está claro quando será corrigido)
    • ATUALIZAÇÃO: os desenvolvedores do Chrome confirmam que estão trabalhando nisso para desktop e Android! sem cronograma ainda.
  • Wrapper JavaScript LawnChair http://brian.io/lawnchair/
    • PRO: wrapper muito limpo para IndexedDB, WebSQL ou qualquer banco de dados que você tenha (pense em polyfill)
    • CON: não é possível armazenar blobs binários, apenas dados: uri (codificação base64) (provavelmente falha fatal devido ao custo de descodificação)
  • IndexedDB JQUERY polyFill https://github.com/axemclion/jquery-indexeddb
    • Parashuram escreveu um bom wrapper JQUERY para a interface bruta do IndexedDB
    • PRO: simplifica muito o uso de IndexedDB, eu esperava adicionar um shim / polyfill para Chrome FileSystemAPI
    • CON: Deve lidar com blobs, mas não consegui fazer funcionar
  • idb.filesystem.js http://ericbidelman.tumblr.com/post/21649963613/idb-filesystem-js-bringing-the-html5-filesystem-api
    • Eric Bidelman @ Google escreveu um PolyFill bem testado, a API FileSystem que usa o banco de dados indexado como uma alternativa
    • PRO: FileSystem API é bem adequada para armazenar blobs
    • PRO: funciona muito bem no FireFox e Chrome
      • PRO: ótimo para sincronização com CouchDB baseado em nuvem
    • CON: não está claro por que, mas não está funcionando no IE10
  • Biblioteca PouchDB JavaScript http://pouchdb.com/
    • ótimo para sincronizar um CouchDB com um banco de dados local (usa WebSQL ou IndexedDB (mas não é problema meu)
    • CON: SEM CONTRAS, PouchDB agora suporta blobs binários para todos os navegadores recentes (IE, Chrome, Firefox, Chrome no celular, etc.), bem como muitos navegadores mais antigos. Esse não era o caso quando fiz este post pela primeira vez.

NOTA: para ver a codificação data: uri do PNG criei um exemplo em: http://jsbin.com/ivefak/1/edit

Recursos desejados / úteis / desnecessários

  • Nenhum aplicativo nativo (EXE, PhoneGap, ObjectiveC, etc) no cliente (aplicativo web puro)
  • Só precisa ser executado no Chrome, FireFox, IE10 mais recente para laptops
  • Desejo muito a mesma solução para tablet Android (IOS também seria bom), mas só precisa de um navegador para funcionar (FF, Chrome, etc.)
  • População de banco de dados inicial rápida
  • REQUISITO: recuperação muito rápida de imagens por aplicativo da web do armazenamento (banco de dados, arquivo)
  • Não se destina aos consumidores. Podemos restringir os navegadores e pedir ao usuário para fazer configurações e tarefas especiais, mas vamos minimizar isso

Implementações IndexedDB

  • Há um excelente artigo sobre como IE, FF e Chrome implementam isso internamente em: http://www.aaron-powell.com/web/indexeddb-storage
  • Em resumo:
    • O IE usa o mesmo formato de banco de dados do Exchange e Active Directory para IndexedDB
    • O Firefox está usando SQLite, então está implementando um banco de dados NoSQL no banco de dados SQL
    • Chrome (e WebKit) estão usando um armazenamento de chave / valor que tem herança em BigTable

Meus resultados atuais

  • Eu escolhi usar uma abordagem IndexedDB (e polyfill com FileSystemAPI para Chrome até que eles forneçam suporte a blob)
  • Para obter os tiles, eu tive um dilema, já que o pessoal do JQUERY está pensando em adicionar isso ao AJAX
  • Eu optei pelo XHR2-Lib de Phil Parsons, que é muito parecido com JQUERY .ajax () https://github.com/pmp/xhr2-lib
  • Desempenho para downloads de 100 MB (IE10 4s, Chrome 6s, FireFox 7s).
  • Não consegui fazer com que nenhum dos wrappers IndexedDB funcionasse para blobs (gramado, PouchDB, jquery-indexeddb etc.)
  • Enrolei meu próprio invólucro e o desempenho é (IE10 2s, Chrome 3s, FireFox 10s)
  • Com o FF, suponho que estamos vendo o problema de desempenho de usar um banco de dados relacional (sqllite) para um armazenamento não sql
  • NOTA, o Chrome tem excelentes ferramentas de depuração (guia do desenvolvedor, recursos) para inspecionar o estado do IndexedDB.

Resultados FINAIS postados abaixo como resposta

Atualizar

O PouchDB agora suporta blobs binários para todos os navegadores recentes (IE, Chrome, Firefox, Chrome no celular, etc.), bem como muitos navegadores mais antigos. Esse não era o caso quando fiz este post pela primeira vez.


1
webstorage não oferece suporte a json, mas a strings, portanto, você pode codificar sua imagem em base64 e exibi-la como dataurls.
mpm

Ok, mas provavelmente não é ideal (ou dentro da cota) para 20 MB de imagens, que na verdade são blocos de mapas escorregadios, que precisam ser buscados e exibidos rapidamente por um aplicativo de mapa LEAFLET conforme você amplia e movimenta.
Dr.YSG de

A pesquisa que você fez é muito útil.
Bogdan Kulynych

meu ponto é que você não precisa lidar com blobs binários se estiver usando imagens PNG.
mpm de

Você está certo, se importaria se eu atualizasse o documento para refletir sua opinião?
Dr.YSG de

Respostas:


25

Resultados Cache de blob offline para mapas deslizantes PNG

Testando

  • 171 arquivos PNG (total de 3,2 MB)
  • Plataformas testadas: Chrome v24, FireFox 18, IE 10
  • Também deve funcionar com Chrome e FF para Android

Buscar no servidor da web

  • usando XHR2 (compatível com quase todos os navegadores) para download de blob do servidor web
  • Eu escolhi o XHR2-Lib de Phil Parsons, que é muito parecido com o JQUERY .ajax ()

Armazenamento

Exibição

  • Estou usando o folheto http://leafletjs.com/ para mostrar os blocos do mapa
  • Eu usei o plugin funcional da camada de blocos de Ishmael Smyrnow para buscar a camada de blocos do banco de dados
  • Eu comparei a camada de blocos baseada em banco de dados com um armazenamento puramente local (localhost: //)
  • Não há diferença perceptível no desempenho! entre usar IndexedDB e arquivos locais!

Resultados

  • Chrome: Fetch (6.551s), Store (8,247s), Tempo total decorrido: (13,714s)
  • FireFox: Buscar (0,422s), Armazenar (31,519s), Tempo total decorrido: (32,836s)
  • IE 10: Buscar (0,668 s), Armazenar: (0,896 s), Tempo total decorrido: (3,758 s)

4

Para seus requisitos, sugiro que desenvolver um novo polyfill baseado em dois outros: API FileSystem para IndexedDB e IndexedDB para WebSQL - é a melhor opção.

O primeiro irá habilitar o suporte para armazenamento de blobs no Chrome (API FileSystem) e Firefox (IndexedDB), enquanto o último deverá fornecer suporte para Android e iOS ( WebSQL ). O que é necessário é apenas fazer com que esses polyfills funcionem juntos, e suponho que não seja difícil.

NB: Como não consegui encontrar nenhuma informação sobre isso na web, você deve testar se o armazenamento de blobs usando o polyfill WebSQL funciona no iOS e no Android. Parece que deve funcionar:

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

Fonte


Estou inclinado para a sua sugestão, mas estou esperando ouvir outras pessoas. Não tenho um android útil, mas seria bom criar um jsBin ou jsFiddle e ver o que funciona no Android.
Dr.YSG 01 de

1
Esses dois blob são diferentes. Sqlite blob é arraybuffer em javascript, enquanto js blob não tem equivalente em sqlite. Blob não pode ser convertido em arraybuffer, embora possa ser clonado estruturalmente.
Kyaw Tun

2

Eu tenho exemplos de cache de mapa (abrir exemplo, descobrir regiões e zooms, alternar offline e regiões descobertas estarão disponíveis).

Existem map.js- camada de mapa para blocos offline, storage.js- implementação de armazenamento baseada em IndexedDb e WebSQL (mas isso apenas testa a implementação com baixo desempenho).

  • Para arquivos do site (html, css, js e etc.) eu prefiro usar o cache do aplicativo.
  • Para armazenamento eu prefiro usar DB indexado (suporte a blob), Web SQL (somente base64), FileWriter (suporte a blob, mas apenas cromo). Francamente, o armazenamento é um grande problema para isso. Você precisa da solução de valor-chave mais rápida que combine todos eles. Eu acho que é uma boa decisão usar a solução existente.
  • Para buscar, usei canvas com CORS. Mas estou pensando em WebWorkers e XHR2 e isso pode ser melhor em vez do canvas porque o canvas tem alguns problemas com CORS em navegadores diferentes e outros (por exemplo, este título foi armazenado incorretamente no opera ).

Informações adicionais sobre os tamanhos de 2 bilhões de cidades ( Minsk ):

  • Zoom - 9, tiles - 2, tamanho - 52 kb, com anterior - 52 kb;
  • Zoom - 10, ladrilhos - 3, tamanho - 72 kb, com anterior - 124 kb;
  • Zoom - 11, ladrilhos - 7, tamanho - 204 kb, com anterior - 328 kb;
  • Zoom - 12, blocos - 17, tamanho - 348 kb, com anterior - 676 ​​kb;
  • Zoom - 13, blocos - 48, tamanho - 820 kb, com anterior - 1,5 MB;
  • Zoom - 14, blocos - 158, tamanho - 2,2 MB, com anterior - 3,7 MB;
  • Zoom - 15, blocos - 586, tamanho - 5,5 MB, com anterior - 9,3 MB;
  • Zoom - 16, blocos - 2264, tamanho - 15 MB, com anterior - 24,3 MB;

Suponho que sejam blocos JPG no formato EGPS3857 deslizante, certo? como estou usando o folheto e fazendo ovelays raster, tive que usar PNG. também confira minha demonstração de uso do PouchDB (que usa o IDB abaixo). stackoverflow.com/questions/16721312/…
Dr.YSG

Ah, sim, você está armazenando em cache instantaneamente, mas sabe onde posso ir para obter um mapa OSM pré-construído (mundial) para diminuir o zoom de 10, 11 ou 12? Nós manteríamos isso em nosso servidor offline.
Dr.YSG

Não, usado PNGcom projeção padrão (EGPS: 3857), mas não importa JPEGou PNGporque usado por imgtag ou canvas. Com meu exemplo, você pode apenas pré-carregar as peças se souber as chaves das peças ( storage.add('x_y_z', 'data:image/png;base64,...')para cada peça armazenada), mas sempre poderá obtê-las se souber apenas os limites (polígono) e os zooms.
tbicr

Quero ter certeza de que não temos problemas de idioma. Você acha que podemos obter um conjunto OSM mundial de blocos deslizantes (PNG ou JPG) para o nível de zoom 10?
Dr.YSG

Você pode obter o formulário de blocos tile.osm.org(renderizador mapnik). Por exemplo http://tile.openstreetmap.org/10/590/329.png( zoom/ x/ y.png). Esses tiles têm Access-Control-Allow-Origin: *cabeçalho para que você possa obtê-los por ajax ou obter dados uri (base64) por canvas. Você já pode baixar azulejos com o seu manifest.json {id: 0-0-0}, mas você deve certificar de que têm direito zoom, x, yseqüência.
tbicr

1

Alguns anos atrás (não exatamente na idade da pedra), eu estava usando um miniaplicativo java assinado que consultava seu servidor quanto aos requisitos de sincronização / atualização, baixava os arquivos apropriados do servidor e os salvava no sistema de arquivos do usuário (não em um banco de dados). Essa solução pode funcionar para você, embora você precise de alguém para escrever o miniaplicativo e assiná-lo. Para soluções de banco de dados, esse miniaplicativo pode usar o jdbc disponível para a maioria dos bancos de dados usando localhost em uma porta adequada (por exemplo, 3306 para MySQL). Acredito que a tag do miniaplicativo está obsoleta no Html5, mas ainda funciona. Nenhuma experiência em tablets Android, então não posso comentar sobre essa parte.


1
Comecei a programar em FORTRAN em 1968 usando um perfurador de cartão. Portanto, as soluções da idade da pedra não são novas para mim.
Dr.YSG de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.