Como estender o localStorage entre dispositivos (sem DB)

10

Objetivo: estender meu já implementado localStorageno meu aplicativo, para ficar bem, não local, eu acho.


Gosto da implementação de salvar configurações simples do usuário com a API de armazenamento local. Eu tenho isso funcionando para minhas necessidades em um aplicativo Web, mas o único problema é que ele é local para a máquina / navegador que está sendo usada / salva. Eu não tenho acesso a uma tabela clássica de estilo MySQL para isso. Gostaria de estender ou adaptar meu armazenamento local para ser transferido para outros navegadores; ou armazene minhas configurações de usuário nos objetos JS do usuário e nas propriedades do objeto JS.

  • Eu gosto da ideia de apenas criar objetos JSON ou JavaScript com cada usuário, sempre que houver um novo usuário, pegue o nome, crie um objeto ou object[key]com o nome e tenha as propriedades padrão das propriedades do campo primeiro, e as variáveis ​​sejam preenchidas e ou substituído quando o usuário os salva.
  • Ou se o acima é desaprovado; gostaria de manter minha implementação de armazenamento local, pois funciona tão bem, e encontrar algum plugin / biblioteca / extensão de algum tipo que me permita também salvá-lo e renderizá-lo em diferentes locais; isso já foi pensado antes. Embora eu adorasse mantê-lo do lado do cliente; Estou aberto a uma solução node.js, bem como a solução python, um tipo de quadro de dados simples deve funcionar o suficiente.
  • Que tal gerar um arquivo com meus localStoragedados? Talvez um arquivo .csv (esses são dados não confidenciais) e ele seja atualizado como o meu localStorage?
doc feriado
fonte
2
Você não pode fazer isso apenas do lado do cliente. Para persistir nas informações do usuário nos navegadores, você precisa de um servidor público e armazenar informações nele. Normalmente, isso é feito usando um banco de dados; se você não quiser usar o mySQL, existem outros tipos de armazenamento de dados. O Firebase está bem próximo do que você imagina, permite armazenar objetos de estrutura arbitrária. (também, JSON é um formato de texto. não existe um objeto JSON)
Chris G
um pouco semelhante a isso: stackoverflow.com/a/60279503/4845566 ?
deblocker 26/02

Respostas:

3

Que tal usar o sqlite?

Apenas um arquivo no seu servidor, como o CSV. Enviando uma solicitação http Para atualizá-la usando a instrução SQL por knex ou algo parecido após atualizar o armazenamento local no lado do cliente.

Pelo menos é melhor do que cvs, eu acho, porque você pode definir várias tabelas, que são mais escaláveis ​​e mais eficientes, sabe, é um banco de dados.

kobako
fonte
2

Estou adicionando meus dois centavos aqui.


Arquivo de exportação / importação (JSON, XML, CSV, TSV, etc.)

Exportação:

Serialize as configurações e faça o download como arquivo.

Importar:

Abra o arquivo de configurações serializadas exportado / baixado.

Código de exemplo:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Settings Export/Import Demo</title>
</head>

<body>
    <div id="display"></div> <br>
    <button onclick="exportSettings();">Export</button>

    <button onclick="resetSettings();">Reset</button> <br><br>
    File to import: <input id="file-input" type="file" accept="application/json"> <br>
    <button onclick="importSettings();">Import</button>
    <script>

        function exportSettings() {
            var json = getSettingsAsJSON();
            var blob = new Blob([json], { type: "application/json" });
            var linkElement = document.createElement("a");

            linkElement.href = URL.createObjectURL(blob);
            linkElement.download = "ThisIsMySettings";

            document.body.appendChild(linkElement);

            linkElement.click();

            document.body.removeChild(linkElement);
        }

        function importSettings() {
            var fileInput = document.getElementById("file-input");

            if (fileInput.files.length > 0) {
                var jsonFile = fileInput.files[0];

                var fileReader = new FileReader();

                fileReader.onload = function (e) {
                    var json = e.target.result;

                    try {
                        var settings = JSON.parse(json);

                        if (settings.hasOwnProperty("userId")) {
                            localStorage["myapp_user_id"] = settings.userId;
                        }

                        if (settings.hasOwnProperty("hello")) {
                            localStorage["myapp_hello"] = settings.hello;
                        }

                        if (settings.hasOwnProperty("data")) {
                            localStorage["myapp_data"] = settings.data;
                        }

                        displaySettings();
                    } catch (ex) {
                        console.error(ex);

                        alert("Error occured while importing settings!");
                    }
                };

                fileReader.readAsText(jsonFile);
            }
        }

        function resetSettings() {
            localStorage["myapp_user_id"] = Math.floor(Math.random() * 100000) + 1;
            localStorage["myapp_hello"] = "Hello World!";
            localStorage["myapp_data"] = JSON.stringify([1, 3, 3, 7]);

            displaySettings();
        }

        function displaySettings() {
            var json = getSettingsAsJSON();

            document.getElementById("display").innerText = json;
        }

        function getSettingsAsJSON() {
            return JSON.stringify({
                userId: localStorage["myapp_user_id"],
                hello: localStorage["myapp_hello"],
                data: localStorage["myapp_data"]
            });
        }

        resetSettings();
    </script>
</body>

</html>

URL (string de consulta)

Exportação:

Codifique as configurações na string de consulta e combine com o URL atual como hiperlink.

Importar:

Visite o hiperlink que contém a string de consulta com configurações codificadas e, em seguida, o JavaScript detecta e carrega as configurações da string de consulta.


Dados codificados em Base64

Exportação:

Serialize as configurações, codifique-as como string Base64 e copie para a área de transferência.

Importar:

Cole a string Base64 da área de transferência na caixa de texto para decodificar, desserializar e carregar as configurações.


Código QR

Exportação:

Codifique as configurações na string de consulta e combine com o URL atual como hiperlink. Em seguida, gere uma imagem de código QR e exiba.

Importar:

Digitalize a imagem do código QR gerado e visite o hiperlink automaticamente.


Servidor HTTP (Node.js) / Armazenamento em nuvem (AWS S3)

Exportação:

HTTP POST para endpoint automaticamente ao atualizar valores, por ID do usuário.

Importar:

HTTP GET do terminal por ID do usuário.


Extra: PouchDB

O banco de dados que sincroniza!

O PouchDB é um banco de dados JavaScript de código aberto inspirado no Apache CouchDB, projetado para funcionar bem no navegador.

O PouchDB foi criado para ajudar os desenvolvedores da Web a criar aplicativos que funcionam tão offline quanto online. Ele permite que os aplicativos armazenem dados localmente enquanto estiverem off-line e os sincronizem com o CouchDB e servidores compatíveis quando o aplicativo voltar a ficar on-line, mantendo os dados do usuário sincronizados, independentemente do próximo login.

DK Dhilip
fonte
Obrigado pela resposta. Melhor ainda; com a primeira importação / exportação - eu poderia fazer isso para que o usuário pudesse simplesmente abrir o arquivo para carregar as configurações? Como isso poderia funcionar?
doc holiday
11
Adicionado código de exemplo para exportação / importação de arquivo JSON.
DK Dhilip 24/02
Ah entendo. Obrigado. Eu só acho que isso é pedir muito do usuário. Se houvesse uma maneira de gerar um hiperlink e enviá-lo por e-mail, talvez. Acho que meus dados contêm muitos caracteres para inserir em uma string de consulta de URL. Como a opção de código QR seria digitalizada?
doc holiday
Se seus dados forem grandes demais para caber na cadeia de caracteres de consulta, talvez você possa experimentar gzip / deflate mais Base64 para ver se ele pode reduzir o tamanho da carga útil e incluir na cadeia de caracteres de consulta? Não sei se isso funcionará suficientemente bem para o seu caso, apenas um pensamento aleatório. Para a opção de código QR, ele pode ser digitalizado por qualquer dispositivo com uma câmera ou digitalizar arquivo de imagem diretamente (a partir de URL comum, URL de dados, arquivo aberto).
DK Dhilip 24/02
Para expandir a ideia de redução do tamanho dos dados, você também pode tentar serializar seus dados manualmente no ArrayBuffer para torná-los o menor possível e, em seguida, aplicar a codificação Base64 a ele, dependendo do método de transporte.
DK Dhilip 24/02
2

Você pode usar a URL como armazenamento se você compactar os parâmetros do usuário.
obtenha os parâmetros que deseja armazenar> json> deflate> codifique para base64> insira o URL

const urlParam = btoa(pako.deflate(JSON.stringify(getUser()), { to: 'string' }));

onload: obtenha os parâmetros do URL> decodifique de base64> inflate> analise json

const user = JSON.parse(pako.inflate(atob(urlParam), { to: 'string' }));

https://jsfiddle.net/chukanov/q4heL8gu/44/

O parâmetro da URL será bastante longo, mas 10 vezes menor que o máximo disponível

Anton Chukanov
fonte
Este! No entanto, quando eu registro meus dados de armazenamento local, são ~ 20k e ~ 8k em caracteres. Eu ainda poderia fazer algo assim?
doc holiday
11
Eu testei com 160k caracteres. Serão 1600 caracteres após a desinflação, até o IE funcionará sem problemas (tamanho máximo da url, por exemplo, - 2048). Navegadores modernos não têm limitações para o comprimento da URL.
Anton Chukanov 26/02
Obrigado! pako requer uma biblioteca ou algo assim? Estou ficando indefinido
doc holiday
11
"Navegadores modernos não têm limitação para o comprimento do URL" é uma suposição falsa, consulte isso . Além disso, pako é uma biblioteca JavaScript que pode ser encontrada aqui ( GitHub , cdnjs ). Por fim, observe também que a taxa de compactação pode variar dependendo do conteúdo dos dados.
DK Dhilip 27/02
2

Em vez de usar o armazenamento local, armazene as configurações do usuário no Sistema de arquivos interplanetário (IPFS) https://ipfs.io/

Basicamente, você colocaria a configuração deles em um formato de dados como JSON e, em seguida, gravá-lo em arquivo e enviá-lo ao IPFS.

Você precisará de uma maneira de identificar quais dados vão para qual usuário. Talvez você possa usar um hash do nome de usuário e senha para nomear seus arquivos ou algo assim. Em seguida, seu usuário sempre poderá acessar o conteúdo em qualquer dispositivo (desde que não esqueça sua senha).

Michael Babcock
fonte
1

Você pode usar uma biblioteca chamada localForageque tem basicamente a mesma API, localStorageexceto que permite armazenar estruturas de dados mais complexas (matrizes, objetos) e também suporta nodejsestilo de retorno de chamada, promessas e async await.

Aqui está um link para o repositório, onde você pode encontrar exemplos de usos e como implementá-lo em seu projeto da maneira que desejar.

C.Gochev
fonte
Obrigado que parece arrumado; mas parece que ele tem as mesmas limitações para um banco de dados que o localStorage normal
doc holiday
1

A melhor maneira de implementar isso sem usar o banco de dados para compartilhar dados, acredito que seja baseado na solução WebRTC , pensei nisso como uma maneira de fazer isso, mas não tenho código para isso (pelo menos por enquanto), então com alguma pesquisa eu encontrei alguém que já fez (não exatamente, mas com alguns ajustes estará pronto) aqui, por exemplo, e sua parte deste artigo webrtc sem um servidor de sinalização

aqui está mais uma fonte: exemplo básico de exemplo de canal de dados

e no github: exemplo básico do canal de dados

O WebRTC não é apenas para bate-papo por vídeo / áudio, também pode ser usado em mensagens de texto e colaboração na edição de texto.

Esta solução foi mencionada em uma das respostas aqui .

Ma'moun othman
fonte
0

Use cookies ou tenha um arquivo para download que os usuários podem levar com eles para carregar quando acessarem outro navegador. Você pode fazer isso com um arquivo de texto, JSON ou JavaScript com dados do objeto.


fonte
Acredito que os cookies são apenas locais também?
doc holiday
Os cookies de terceiros podem ser usados ​​por vários sites, se confiarem na mesma "fonte".
0

Você pode usar o Redis . É um armazenamento de estrutura de dados na memória, usado como um banco de dados. Você pode armazenar seus dados em formatos de par de chaves. Também torna seu aplicativo rápido e eficiente.

Deeksha gupta
fonte
0

Obviamente, a melhor abordagem é usar um banco de dados. No entanto, se você está inclinado a usar um banco de dados, a melhor abordagem possível é usar uma combinação de técnicas nas quais acredito que você já tenha tocado, por isso vou ajudá-lo a conectar os pontos aqui.

Etapas necessárias:

  1. API LocalStorage (como já está funcionando parcialmente para você).
  2. Crie um nó de extremidade Nó ou Python (ou com o que você se sente confortável) para dados de configurações GET e POST.
  3. Crie um arquivo userSettings.JSON no seu servidor de API.

Instruções:

Você usaria seu localStorage da mesma maneira que está usando agora (estado de trabalho atual).

Para mover ou ter configurações do usuário em diferentes dispositivos, um arquivo userSettings.JSON (servindo como banco de dados de documentos) será usado para armazenar e importar configurações do usuário.

Seu ponto de extremidade da API seria usado para obter as configurações do usuário, se não existirem no localStorage. Na atualização das configurações, atualize seu localStorage e, em seguida, POST / UPDATE as novas configurações no seu arquivo userSettings.JSON usando seu terminal.

O terminal da API será usado apenas para manter (ler e gravar) o arquivo userSettings.JSON. Você precisará de um método / função para criar, atualizar e talvez excluir configurações do seu arquivo. Como você já deve saber, um formato de arquivo JSON não é muito diferente de um banco de dados MongoDB. Nesse caso, você está apenas criando os métodos necessários para gerenciar seu arquivo.

Eu espero que isso ajude!

mohammedabdulai
fonte
-1

Você pode resolver isso sem um banco de dados, mas eu não o recomendaria. Basicamente, você tem pares (usuário, localStorage) e, quando um determinado usuário se identifica, seu localStorage deve ser fornecido de uma maneira. Você pode dizer aos usuários para armazenar seus armazenamentos locais em sua própria máquina, mas eles terão que copiá-los para outras máquinas, que exigem muito trabalho e nunca ganharão popularidade. Pode-se executar manualmente um pedaço de Javascript no console do navegador para garantir que o localStorage tenha seus dados e ter que copiar o localStorage nas máquinas é apenas um pouco mais fácil do que fazer manualmente a coisa toda.

Você pode colocar as informações localStorage codificadas em um URL, mas além do problema de tamanho do URL, que pode se tornar um problema e os problemas de codificação sempre presentes, todo o localStorage pode ser monitorado por terceiros, tendo acesso ao seu roteador. Eu sei que você disse que os dados não é sensível, mas eu acredito que você que não é sensível ainda . Porém, quando os usuários usarem isso, se for conveniente, eles também armazenarão dados confidenciais ou, seus clientes poderão ter essas tarefas para você ou até você perceberá que precisa armazenar dados lá que não sejam 100% públicos.

Além disso, na prática, você enfrentará problemas muito sérios de sincronização, ou seja, é ótimo tornar o localStorage independente de como será, mas qual é a versão real? Se você trabalha regularmente em 10 sessões diferentes, a sincronização do localStorages se torna um problema difícil. Isso significa que o localStorage precisa ser marcado com data e hora.

Portanto, você precisará de um local central, um servidor para armazenar a última versão localStorage salva. Se você for evitado pelos bancos de dados por alguns motivos desconhecidos, poderá armazenar localStorages em arquivos que identificam o usuário, como

johndoe.json

e, em seguida, você precisará implementar um recurso de exportação, que enviará o JSON atual do usuário ao servidor e o salvará em um arquivo e um recurso de importação, que fará o download do arquivo armazenado para o usuário e garantirá que localStorage seja atualizado adequadamente. Você pode fazer os dois juntos também, implementando uma sincronização.

Até agora, isso é simples, mas e se o usuário já tiver alguns dados úteis dentro de seu localStorage local e também no servidor? A abordagem mais simples é substituir uma pela outra, mas qual? Se estivermos importando, o local será substituído, se estiver exportando, o servidor será substituído, se sincronizarmos, o anterior será substituído.

No entanto, em alguns casos, você deseja mesclar duas localStorages do mesmo usuário, portanto:

novos elementos

Acredito que, se um elemento é novo, deve-se saber de alguma maneira que ele foi criado nesta sessão, o que é útil saber, porque isso significa que na outra sessão com a qual estamos nos fundindo, esse novo item não foi removido e, portanto, é intuitivo adicioná-lo.

mudanças de elemento

Se o mesmo elemento for diferente nos dois casos, a versão mais recente deverá prevalecer.

elementos removidos

O caso interessante é quando em uma sessão foi removido e na outra foi atualizado. Nesse caso, acho que a mudança mais recente deve prevalecer.


No entanto, apesar dos seus melhores esforços, os usuários ainda podem atrapalhar (e também o seu software), portanto, fazer backup de cada sessão no servidor faz sentido.

Lajos Arpad
fonte