Jak rozszerzyć localStorage na urządzenia (bez DB)

10

Cel: rozszerzenie mojej już zaimplementowanej localStoragew mojej aplikacji, aby być dobrze, chyba lokalnie.


Podoba mi się implementacja zapisywania prostych ustawień użytkownika za pomocą interfejsu API lokalnego magazynu. Mam to działa na moje potrzeby w aplikacji internetowej, ale jedynym problemem jest to, że lokalny jest używany / zapisany komputer / przeglądarka. Nie mam do tego dostępu do klasycznej tabeli w stylu MySQL. Chciałbym rozszerzyć lub dostosować moją lokalną pamięć do innych przeglądarek; lub zapisz moje ustawienia użytkownika w obiektach JS użytkownika i właściwościach obiektu JS.

  • Podoba mi się pomysł tworzenia po prostu obiektów JSON lub JavaScript dla każdego użytkownika, ilekroć jest nowy użytkownik, weź nazwę, utwórz obiekt lub object[key]z nazwą i najpierw ustaw domyślne właściwości pola, a zmienne zostaną zapełnione i lub zastępowane, gdy użytkownik je zapisuje.
  • Lub jeśli powyższe jest niezadowolone; chciałbym zachować moją implementację localstorage, ponieważ działa ona tak dobrze, i znaleźć wtyczkę / bibliotekę / rozszerzenie, które pozwala mi również zapisać to i ponownie renderować w różnych lokalizacjach; trzeba o tym pomyśleć wcześniej. Chociaż chciałbym zachować to po stronie klienta; Jestem otwarty na rozwiązanie node.js, a także rozwiązanie python, prosta ramka danych powinna działać wystarczająco dobrze.
  • Co z generowaniem pliku z moimi localStoragedanymi? Być może plik .csv (to nie są dane wrażliwe) i czy ma aktualizować tak jak mój localStorage?
doc wakacje
źródło
2
Nie możesz zrobić tego tylko po stronie klienta. Aby zachować informacje o użytkowniku w różnych przeglądarkach, potrzebujesz publicznego serwera i przechowuj na nim informacje. Zazwyczaj odbywa się to za pomocą bazy danych; jeśli nie chcesz używać mySQL, istnieją inne rodzaje przechowywania danych. Firebase jest bardzo zbliżony do tego, co sobie wyobrażasz, pozwala przechowywać obiekty o dowolnej strukturze. (również JSON jest formatem tekstowym. Nie ma czegoś takiego jak obiekt JSON)
Chris G
nieco podobny do tego: stackoverflow.com/a/60279503/4845566 ?
deblocker

Odpowiedzi:

3

Co z użyciem sqlite?

Tylko jeden plik na serwerze, np. Csv. Wysyłanie żądania http Aby zaktualizować go za pomocą instrukcji SQL za pomocą knex lub czegoś podobnego po zaktualizowaniu magazynu lokalnego po stronie klienta.

Myślę, że przynajmniej lepiej niż cvs, ponieważ możesz zdefiniować kilka tabel, które są bardziej skalowalne i wydajniejsze, wiesz, to baza danych.

kobako
źródło
2

Dodam tutaj moje dwa centy.


Eksportuj / importuj plik (JSON, XML, CSV, TSV itp.)

Eksport:

Serializuj ustawienia i pobierz je jako plik.

Import:

Otwórz wyeksportowany / pobrany plik ustawień serializowanych.

Przykładowy kod:

<!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 (ciąg zapytania)

Eksport:

Zakoduj ustawienia w ciągu zapytania i połącz z bieżącym adresem URL jako hiperłączem.

Import:

Odwiedź hiperłącze zawierające ciąg zapytania z zakodowanymi ustawieniami, a następnie JavaScript wykrywa i ładuje ustawienia z ciągu zapytania.


Dane zakodowane w standardzie Base64

Eksport:

Ustawienia serializacji następnie zakoduj jako ciąg Base64, a następnie skopiuj do schowka.

Import:

Wklej ciąg Base64 ze schowka do pola tekstowego, aby dekodować, deserializować i ładować ustawienia.


Kod QR

Eksport:

Zakoduj ustawienia w ciągu zapytania i połącz z bieżącym adresem URL jako hiperłączem. Następnie wygeneruj obraz i wyświetl kod QR.

Import:

Zeskanuj wygenerowany obraz kodu QR i automatycznie odwiedź hiperłącze.


Serwer HTTP (Node.js) / Cloud Storage (AWS S3)

Eksport:

POST HTTP do punktu końcowego automatycznie podczas aktualizacji wartości według identyfikatora użytkownika.

Import:

HTTP GET z punktu końcowego według identyfikatora użytkownika.


Dodatkowo: PouchDB

Baza danych, która synchronizuje!

PouchDB to baza danych JavaScript typu open source zainspirowana przez Apache CouchDB , zaprojektowana tak, aby działała dobrze w przeglądarce.

PouchDB został stworzony, aby pomóc twórcom stron internetowych w tworzeniu aplikacji, które działają zarówno offline, jak i online. Umożliwia aplikacjom przechowywanie danych lokalnie w trybie offline, a następnie synchronizowanie ich z CouchDB i kompatybilnymi serwerami, gdy aplikacja jest ponownie w trybie online, utrzymując synchronizację danych użytkownika bez względu na to, gdzie następnym razem się zaloguje.

DK Dhilip
źródło
Dzięki za odpowiedzi. Najlepszy jak na razie; przy pierwszym imporcie / eksporcie - czy mogę to zrobić, aby użytkownik mógł po prostu otworzyć plik do załadowania ustawień? Jak to może działać?
doc wakacje
1
Dodano przykładowy kod eksportu / importu plików JSON.
DK Dhilip
O, rozumiem. Dziękuję Ci. Myślę, że to trochę za dużo od użytkownika. Jeśli istnieje sposób, mogę wygenerować hiperłącze i wysłać je do nich pocztą e-mail. Myślę, że moje dane zawierają zbyt wiele znaków, aby umieścić je w ciągu zapytania adresu URL. Jak skanowana byłaby opcja kodu QR?
doc wakacje
Jeśli twoje dane są zbyt duże, aby zmieściły się w ciągu zapytania, być może możesz poeksperymentować z gzip / deflate plus Base64, aby sprawdzić, czy może zmniejszyć rozmiar ładunku i dołączyć do ciągu zapytania? Nie wiem, czy to zadziała wystarczająco dobrze dla twojej sprawy, tylko przypadkowa myśl. W przypadku opcji kodu QR może być skanowane przez dowolne urządzenie z kamerą lub bezpośrednio skanować plik obrazu (ze zwykłego adresu URL, adresu URL danych, otwartego pliku).
DK Dhilip
Aby rozwinąć pomysł zmniejszenia rozmiaru danych, możesz również spróbować ręcznie serializować dane do ArrayBuffer, aby były jak najmniejsze, a następnie zastosować do niego kodowanie Base64, w zależności od metody transportu.
DK Dhilip
2

Możesz użyć adresu URL jako miejsca do przechowywania, jeśli spakujesz parametry użytkownika.
pobierz parametry, które chcesz zapisać> json> deflate> koduj do base64> wciśnij w adres URL

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

onload: pobierz parametry z adresu URL> dekoduj z base64> inflate> parsuj json

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

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

Adres URL będzie dość długi, ale dostępny 10 razy mniej niż maksimum

Anton Chukanov
źródło
To! Jednak gdy konsola loguje moje dane lokalnego magazynu, jest to ~ 20k i ~ 8k znaków. Czy nadal mogę zrobić coś takiego?
doc wakacje
1
Testowałem ze znakami 160k. Będzie wynosić 1600 znaków po spuszczeniu powietrza, nawet IE będzie działać bez problemów (maksymalna długość adresu URL np. - 2048). Nowoczesne przeglądarki nie mają ograniczenia długości adresu URL.
Anton Chukanov
Dzięki! czy pako wymaga biblioteki czy czegoś? Dostaję pakiet niezdefiniowany
doc wakacje
1
„Nowoczesne przeglądarki nie mają ograniczenia długości adresu URL” to fałszywe założenie, zapoznaj się z tym . Pako to także biblioteka JavaScript, którą można znaleźć tutaj ( GitHub , cdnjs ). Na koniec należy również pamiętać, że współczynnik kompresji może się różnić w zależności od zawartości danych.
DK Dhilip
2

Zamiast używać localstorage, przechowuj ustawienia użytkownika w Międzyplanetarnym Systemie Plików (IPFS) https://ipfs.io/

Zasadniczo umieściłbyś ich ustawienie w formacie danych, takim jak JSON, a następnie zapisałeś je do pliku i wypychałeś do IPFS.

Będziesz potrzebował sposobu na określenie, które dane trafiają do którego użytkownika. Może możesz użyć skrótu nazwy użytkownika i hasła, aby nazwać swoje pliki lub coś w tym rodzaju. Wówczas użytkownik zawsze będzie mógł uzyskać dostęp do swoich treści na dowolnym urządzeniu (o ile nie zapomni swojego hasła).

Michael Babcock
źródło
1

Możesz użyć biblioteki o nazwie, localForagektóra ma w zasadzie ten sam interfejs API, localStoragez wyjątkiem tego, że pozwala przechowywać bardziej złożone struktury danych (tablice, obiekty), a także obsługuje nodejsstyl wywołania zwrotnego, obietnic i async await.

Oto link do repozytorium, w którym można znaleźć przykładowe zastosowania i jak zaimplementować je w swoim projekcie tak, jak lubisz.

C.Gochev
źródło
Dzięki, że wygląda schludnie; ale wygląda na to, że ma takie same ograniczenia do DB jak normalne localStorage
doc holiday
1

Najlepszym sposobem na wdrożenie tego bez użycia bazy danych do udostępniania danych, uważam, że jest to oparte na rozwiązaniu WebRTC , pomyślałem o tym, ale nie mam do tego kodu (przynajmniej na razie), więc z niektóre wyszukiwania znalazłem, że ktoś już to zrobił (nie do końca, ale z pewnymi poprawkami będzie gotowy) tutaj, na przykład, a jego część tego artykułu webrtc bez serwera sygnalizacyjnego

oto jeszcze jedno źródło: przykładowa demonstracja podstawowego kanału danych

i na github: podstawowy przykład kanału danych

WebRTC służy nie tylko do czatu wideo / audio, ale może być również wykorzystywany do wysyłania wiadomości tekstowych i współpracy przy edycji tekstu.

To rozwiązanie wspomniano nawet w jednej z odpowiedzi tutaj .

Ma'moun othman
źródło
0

Używaj plików cookie lub pobierz plik, który użytkownicy mogą zabrać ze sobą, aby załadować, gdy uzyskują dostęp do innej przeglądarki. Możesz to zrobić za pomocą pliku tekstowego, JSON lub JavaScript z danymi obiektowymi.


źródło
Uważam, że pliki cookie są również lokalne?
doc wakacje
Pliki cookie stron trzecich mogą być wykorzystywane przez wiele witryn, jeśli opierają się na tym samym „źródle”.
0

Możesz użyć Redis . Jest to magazyn struktur danych w pamięci, używany jako baza danych. Możesz przechowywać swoje dane w formatach par kluczy. Dzięki temu aplikacja jest szybka i wydajna.

Deeksha gupta
źródło
0

Oczywiście najlepszym rozwiązaniem jest użycie bazy danych. Jeśli jednak masz skłonność do korzystania z bazy danych, najlepszym możliwym podejściem jest użycie kombinacji technik, które, jak sądzę, już się dotknąłeś, więc pomogę ci połączyć kropki tutaj.

Potrzebne kroki:

  1. LocalStorage API (ponieważ już częściowo działa dla Ciebie).
  2. Zbuduj punkt końcowy węzła lub języka Python (lub z czym masz swobodę) do danych ustawień GET i POST.
  3. Utwórz plik userSettings.JSON na serwerze API.

Instrukcje:

Używałbyś swojego localStorage w taki sam sposób, jak teraz go używasz (aktualny stan pracy).

Aby przenieść lub skonfigurować ustawienia użytkownika na różnych urządzeniach, plik userSettings.JSON (służący jako baza danych dokumentów) będzie używany do przechowywania i importowania ustawień użytkownika.

Twój punkt końcowy interfejsu API byłby używany do GET ustawienia użytkownika, jeśli nie istnieją w localStorage. Po aktualizacji ustawień zaktualizuj localStorage, a następnie POST / UPDATE nowe ustawienia w pliku userSettings.JSON przy użyciu punktu końcowego.

Punkt końcowy interfejsu API będzie używany tylko do obsługi (odczytu i zapisu) pliku userSettings.JSON. Będziesz potrzebował metody / funkcji do tworzenia, aktualizowania i być może usuwania ustawień w swoim pliku. Jak zapewne wiesz, format pliku JSON niewiele różni się od bazy danych MongoDB. W tym przypadku po prostu tworzysz metody potrzebne do zarządzania plikiem.

Mam nadzieję, że to pomoże!

mohammedabdulai
źródło
-1

Możesz rozwiązać ten problem bez bazy danych, ale nie poleciłbym tego. Zasadniczo masz pary (użytkownik, localStorage), a gdy dany użytkownik się zidentyfikuje, jego localStorage należy podać w sposób. Możesz powiedzieć użytkownikom, aby przechowali swoje lokalne magazyny na własnym komputerze, ale wtedy będą musieli skopiować je na inne maszyny, co jest pracochłonne i nigdy nie zyska popularności. Można ręcznie uruchomić fragment Javascript w konsoli przeglądarki, aby upewnić się, że localStorage ma swoje dane, a konieczność skopiowania localStorage na różne maszyny jest tylko nieznacznie łatwiejsza niż zrobienie tego ręcznie.

Możesz umieścić informacje localStorage zakodowane w adresie URL, ale oprócz problemu z długością adresu URL, który może stać się problemem i wciąż występującymi problemami z kodowaniem, całe localStorage może być monitorowane przez stronę trzecią, mającą dostęp do routera. Wiem, że powiedział, że dane te nie są wrażliwe, ale wierzę, że to nie jest wrażliwy jeszcze . Ale gdy użytkownicy skorzystają z tego, jeśli będzie to wygodne, będą również przechowywać poufne dane lub, Twoi klienci mogą mieć dla ciebie takie zadania, a nawet możesz zdać sobie sprawę, że musisz przechowywać dane, które nie są w 100% publiczne.

Poza tym w praktyce napotkasz bardzo poważne problemy z synchronizacją, to znaczy, że fajnie jest sprawić, że localStorage będzie agnostyczny, ale jaka jest prawdziwa wersja? Jeśli regularnie pracujesz nad 10 różnymi sesjami, synchronizacja localStorages staje się trudnym problemem. Oznacza to, że localStorage wymaga znacznika czasu.

Potrzebujesz więc centralnego miejsca, serwera do przechowywania ostatnio zapisanej wersji localStorage. Jeśli bazy danych unikają z jakichś niewiadomych powodów, możesz przechowywać localStorages w plikach identyfikujących użytkownika, takich jak

johndoe.json

a następnie musisz zaimplementować funkcję eksportu, która wyśle ​​bieżący kod JSON użytkownika na serwer i zapisze go w pliku oraz funkcję importu, która pobierze plik przechowywany dla użytkownika i zapewni aktualizację localStorage odpowiednio. Możesz zrobić oba razem, implementując synchronizację.

Jak dotąd jest to proste, ale co zrobić, jeśli użytkownik ma już jakieś przydatne dane w swoim lokalnym localStorage i na serwerze? Najprostszym podejściem jest ominięcie siebie, ale które? Jeśli importujemy, to lokalny jest nadpisywany, jeśli eksportujemy, to ten na serwerze jest nadpisywany, jeśli synchronizujemy, starsze jest nadpisywane.

Jednak w niektórych przypadkach chcesz scalić dwa lokalne Magazyny tego samego użytkownika, więc:

nowe elementy

Uważam, że jeśli element jest nowy, należy w pewien sposób wiedzieć, że został utworzony w tej sesji, co warto wiedzieć, ponieważ oznacza to, że w innej sesji, z którą się łączymy, ten nowy element nie został usunięty i dlatego dodawanie go jest intuicyjne.

zmiany elementów

Jeśli ten sam element jest inny w obu przypadkach, wówczas powinna obowiązywać nowsza wersja.

usunięte elementy

Ciekawym przypadkiem jest to, że w jednej sesji został on usunięty, aw drugiej zaktualizowany. W tym przypadku myślę, że nowsza zmiana powinna mieć pierwszeństwo.


Jednak pomimo dołożenia wszelkich starań użytkownicy mogą nadal popsuć (i oprogramowanie również) rzeczy, więc tworzenie kopii zapasowej każdej sesji na serwerze ma sens.

Lajos Arpad
źródło