如何跨设备扩展localStorage(无数据库)


10

目标:扩展我已经localStorage在我的应用程序中实现的功能,当然,应该是非本地的。


我喜欢使用本地存储API保存简单用户设置的实现。我可以在Web应用程序中满足我的需要,但是唯一的问题是它对于正在使用/保存的机器/浏览器是本地的。为此,我无法访问经典的MySQL样式表。我想扩展或调整我的本地存储以继承到其他浏览器;或将我的用户设置存储在用户JS对象和JS对象属性中。

  • 我喜欢这样的想法:只要有新用户,就为每个用户创建JSON或JavaScript对象,并使用名称,创建对象或object[key]名称,并首先使字段属性为默认变量,然后填充变量,或者用户保存它们时覆盖。
  • 或者,如果上述观点不被接受;希望保留我的localstorage实施,因为它运行得很好,并找到了一个插件/库/扩展,使我也可以保存该并在不同位置重新渲染;这是必须要考虑的。尽管我很乐意将其保留在客户端;我对node.js解决方案以及python解决方案持开放态度,一个简单的各种数据框就足够了。
  • 用我的localStorage数据生成文件怎么办?也许是一个.csv文件(这是非敏感数据),并且像我localStorage一样更新了吗?

2
您不能仅做此客户端。要在浏览器中保留用户信息,您需要一个公共服务器并在其上存储信息。通常,这是使用数据库完成的。如果您不想使用mySQL,则还有其他类型的数据存储。Firebase非常接近您的想象,它允许您存储任意结构的对象。(而且JSON是一种文本格式。没有JSON对象之类的东西)
克里斯·G

Answers:


3

那么使用sqlite呢?

服务器上只有一个文件,例如csv。发送http请求在客户端更新本地存储后,通过knex或类似方法使用SQL语句更新它。

至少它比我认为的cvs好,因为您可以定义多个表,这是一个数据库,它具有更高的可伸缩性和效率。


2

我在这里加两分钱。


导出/导入文件(JSON,XML,CSV,TSV等)

出口:

序列化设置并将其下载为文件。

进口:

打开导出/下载的序列化设置文件。

示例代码:

<!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(查询字符串)

出口:

将设置编码为查询字符串,并与当前URL组合为超链接。

进口:

访问包含查询字符串和编码设置的超链接,然后JavaScript从查询字符串中检测并加载设置。


Base64编码数据

出口:

序列化设置,然后将其编码为Base64字符串,然后复制到剪贴板。

进口:

将Base64字符串从剪贴板粘贴到文本框中以解码,反序列化和加载设置。


二维码

出口:

将设置编码为查询字符串,并与当前URL组合为超链接。然后生成一个QR码图像并显示。

进口:

扫描生成的QR码图像并自动访问超链接。


HTTP服务器(Node.js)/云存储(AWS S3)

出口:

通过用户ID更新值时,HTTP POST自动到端点。

进口:

通过用户ID从端点进行的HTTP GET。


附加:PouchDB

同步的数据库!

PouchDB是一个受Apache CouchDB启发的开源JavaScript数据库,旨在在浏览器中良好运行。

PouchDB的创建是为了帮助Web开发人员构建脱机工作以及在线工作的应用程序。它使应用程序可以在脱机时将数据存储在本地,然后在应用程序重新联机时将其与CouchDB和兼容服务器同步,从而使用户的数据无论在下次登录时都保持同步。


感谢您的回复。最好的一个 第一次导入/导出-我可以做到这一点,以便用户可以简单地打开文件以加载设置?那怎么工作?
doc假日

1
添加了用于JSON文件导出/导入的示例代码。
DK Dhilip

知道了 谢谢。我只是认为这对用户提出了很多要求。如果可以的话,我可以生成超链接并将其通过电子邮件发送给他们。我认为我的数据包含太多字符,无法放入URL查询字符串。QR码选项将如何被扫描?
doc假日

如果您的数据太大而无法容纳查询字符串,那么您可以尝试使用gzip / deflate和Base64来查看它是否可以减小有效负载大小并包含在查询字符串中?我不知道这对您的情况是否足够有效,只是一个偶然的想法。对于QR码选项,可以使用相机在任何设备上对其进行扫描,或者直接扫描图像文件(来自普通URL,数据URL,打开文件)。
DK Dhilip

为了扩大数据大小的想法,您还可以尝试将数据手动序列化到ArrayBuffer中,以使其尽可能小,然后根据传输方法对其应用Base64编码。
DK Dhilip

2

如果压缩用户参数,则可以使用URL作为存储。
获取要存储的参数> json> deflate>编码为base64>推入URL

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

onload:从url获取参数>从base64解码>膨胀>解析json

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

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

url参数将很长,但比最大可用量少10倍


这个!但是,当我用控制台记录我的本地存储数据时,它的字符数约为20k和8k。我还能做这样的事情吗?
doc假日

1
我已经测试了16万个字符。放气后将是1600个字符,即使IE也可以正常工作(最大URL长度,即-2048)。现代浏览器对网址长度没有限制。
安东·楚卡诺夫

谢谢!pako是否需要图书馆或其他服务?我正在获取未定义的pako
doc假日

1
“现代的浏览器的网址长度没有限制”是一个错误的假设,请参阅。另外,pako是一个JavaScript库,可以在这里找到(GitHubcdnjs)。最后,请注意压缩率会根据数据内容而有所不同。
DK Dhilip

2

代替使用本地存储,将用户的设置存储在行星际文件系统(IPFS)https://ipfs.io/中

基本上,您可以将其设置设为JSON之类的数据格式,然后将其写入文件并将其推送到IPFS。

您将需要一种方法来识别将哪些数据分配给哪个用户。也许您可以使用用户名和密码的哈希来命名文件或类似名称。这样,您的用户将始终能够在任何设备上访问其内容(只要他们没有忘记密码)。


1

您可以使用一个称为的库localForage,该库与API基本上具有相同的API,localStorage不同之处在于它可以存储更复杂的数据结构(数组,对象),还支持nodejs样式回调,承诺和async await

这是一个到资源库的链接 ,您可以在其中找到示例用法以及如何以自己喜欢的方式在项目中实现它。


谢谢,看起来很整洁。但看起来它对数据库的限制与普通的localStorage相同
doc假日

1

最好的方法是不使用数据库共享数据来实现这一点,我认为它是基于WebRTC解决方案的,我认为这是一种实现方法,但我没有代码(至少到目前为止),因此一些搜索,我发现有人已经做到了(不完全,但也有一些调整,将准备好),在这里,例如,它的这篇文章的一部分,而不信令服务器的WebRTC

这是另一个来源:数据通道基本示例演示

并在github上:数据通道基本示例

WebRTC不仅用于视频/音频聊天,还可以用于文本消息收发以及文本编辑中的协作。

这个解决方案甚至在这里的答案之一中提到。


0

使用cookie或具有可下载文件,供用户在访问其他浏览器时随身携带以加载。您可以使用带有对象数据的文本,JSON或JavaScript文件来执行此操作。


我相信Cookie也是本地的?
doc假日

如果第三方Cookie依靠相同的“源”,则它们可以被多个网站使用。

0

您可以使用Redis。它是内存中的数据结构存储,用作数据库。您可以以密钥对格式存储数据。它还使您的应用程序快速有效。


0

显然,最好的方法是使用数据库。但是,如果您倾向于使用数据库,那么可能的最佳方法是使用多种技术的组合,我相信您已经接触过这些技术,因此在这里我将帮助您建立联系。

所需步骤:

  1. LocalStorage API(因为它已经部分为您工作)。
  2. 构建一个GET或POST设置数据的Node或Python(或您喜欢的)端点。
  3. 在您的API服务器上创建一个userSettings.JSON文件。

说明:

您将使用与现在使用本地存储相同的方式(当前工作状态)。

为了在不同设备上移动或具有用户设置,将使用userSettings.JSON文件(用作文档数据库)来存储和导入用户设置。

如果localStorage中不存在您的API终结点,则将用于获取用户设置。更新设置时,请更新您的localStorage,然后使用终结点在userSettings.JSON文件中发布/更新新设置。

您的API终结点将仅用于维护(读取和写入)userSettings.JSON文件。您将需要一种方法/函数来创建,更新,甚至删除文件中的设置。您可能已经知道,JSON文件格式与MongoDB数据库没有太大区别。在这种情况下,您只是在创建管理文件所需的方法。

我希望这有帮助!


-1

您可以在没有数据库的情况下解决此问题,但我不建议您这样做。基本上,您有(用户,localStorage)对,并且当给定用户标识自己时,应该以某种方式提供他/她的localStorage。您可以告诉用户将本地存储存储在自己的计算机上,但是随后他们将不得不将其复制到其他计算机上,这是劳动密集型的,并且永远不会普及。可以在其浏览器的控制台中手动运行Javascript块,以确保localStorage拥有其数据,并且必须跨机器复制localStorage仅比手动完成整个过程要容易一些。

您可以将localStorage信息编码为URL,但是除了URL长度的问题(可能会成为问题以及永远存在的编码问题)之外,您的整个localStorage都可以由访问路由器的第三方监视。我知道你说的数据是不敏感的,但我相信你,这是不敏感尚未。但是一旦用户使用它,如果方便的话,他们也将存储敏感数据,或者,您的客户可能为您执行了此类任务,甚至您可能意识到您需要在此存储不是100%公开的数据。

除此之外,在实践中,您还将面临非常严重的同步问题,也就是说,使localStorage不可知是一件好事,但是什么才是真正的版本?如果您定期进行10个不同的会话,那么同步localStorage就会成为一个难题。这意味着需要对localStorage加上时间戳。

因此,您将需要一个中央位置,一台服务器来存储上次保存的localStorage版本。如果由于某些未知原因而被数据库避免,则可以将localStorages存储在标识用户的文件中,例如

johndoe.json

然后,您将需要实现导出功能,该功能会将用户的当前JSON发送到服务器并将其保存到文件中,并具有导入功能,该功能将下载为用户存储的文件并确保localStorage得到更新相应地。您也可以将两者一起进行,以实现同步。

到目前为止,这很简单,但是如果用户在其本地localStorage内部和服务器上已经有一些有用的数据,该怎么办?最简单的方法是将另一个覆盖,但是哪个覆盖?如果要导入,则将覆盖本地的一个,如果要导出,则将覆盖服务器上的一个,如果我们进行同步,则将覆盖较旧的一个。

但是,在某些情况下,您希望合并同一用户的两个localStorage,因此:

新元素

我认为,如果一个元素是新元素,则应该以某种方式知道它是在本届会议上创建的,这很有用,因为这意味着在我们正在与之合并的另一届会议上,这一新项目并未被删除。因此添加它很直观。

元素变化

如果在两种情况下相同的元素不同,则应以较新的版本为准。

删除的元素

有趣的情况是,在一个会话中将其删除而在另一会话中将其更新。在这种情况下,我认为应该以较新的更改为准。


但是,尽管您尽了最大的努力,但用户可能仍然会弄乱(以及您的软件),因此备份服务器上的每个会话都是有意义的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.