计算localStorage空间的使用情况

IT技术 javascript size storage local-storage capacity
2021-02-09 14:35:55

我正在使用 Bespin 编辑器和 HTML5 的 localStorage 创建一个应用程序。它在本地存储所有文件并帮助处理语法,使用 JSLint 和其他一些 CSS 和 HTML 解析器来帮助用户。

我想计算使用了多少 localStorage 限制以及实际使用了多少。今天这可能吗?我在想不要简单地计算存储的位。但话又说回来,我不确定还有什么是我无法衡量自己的。

6个回答

您可以通过使用 JSON 方法将整个 localStorage 对象转换为 JSON 字符串来大致了解:

JSON.stringify(localStorage).length

我不知道它的字节精度有多高,特别是如果您使用其他对象时添加的标记的几个字节 - 但我认为这比认为您只推 28K 而不是做 280K(或副 -反之)。

请注意,正如您在链接的测试中指出的那样,这是一个以字符而不是字节为单位的大小:“JavaScript 中的字符串是 UTF-16,因此每个字符需要两个字节的内存。这意味着虽然许多浏览器有 5 MB 限制,您只能存储 250 万个字符。”
2021-03-15 14:35:55
这实际上足够准确,可以使用。当 localStorage 在 Chrome 14 上达到最大值时,JSON.stringify(localStorage).length === 2636625 或 2.51448 MB,已经足够接近 ( dev-test.nemikor.com/web-storage/support-test )。与 try{} catch{} 配合使用,您就可以构建一个辅助类了。
2021-04-03 14:35:55

我没有找到一种通用的方法来获得我需要的浏览器的剩余限制,但我确实发现当你达到限制时会弹出一条错误消息。这当然在每个浏览器中都不同。

为了最大限度地发挥作用,我使用了这个小脚本:

for (var i = 0, data = "m"; i < 40; i++) {
    try { 
        localStorage.setItem("DATA", data);
        data = data + data;
    } catch(e) {
        var storageSize = Math.round(JSON.stringify(localStorage).length / 1024);
        console.log("LIMIT REACHED: (" + i + ") " + storageSize + "K");
        console.log(e);
        break;
    }
}
localStorage.removeItem("DATA");

从中我得到了这个信息:

谷歌浏览器

  • DOM 异常:
    • 代码:22
    • 消息:“无法在‘存储’上执行‘setItem’:设置‘数据’的值超出了配额。”
    • 名称:“配额超出错误”

火狐浏览器

  • DOM 异常:
    • 代码:1014
    • 消息:“已达到持久存储的最大大小”
    • 名称:“NS_ERROR_DOM_QUOTA_REACHED”

苹果浏览器

  • DOM 异常:
    • 代码:22
    • 消息:“配额超出错误:DOM 异常 22”
    • 名称:“配额超出错误”

Internet Explorer、Edge(社区)

  • DOM 异常:
    • 代码:22
    • 消息:“配额超出错误”
    • 名称:“配额超出错误”

我的解决方案

到目前为止,我的解决方案是在用户每次保存任何内容时添加一个额外的调用。如果异常被捕获,那么我会告诉他们他们的存储容量不足。


编辑:删除添加的数据

我忘了提到要真正起作用,您需要删除DATA最初设置项目。更改通过使用removeItem()函数反映在上面

非常好,i在每种情况下达到这一点的value是多少?
2021-03-16 14:35:55
好的,那么我可以将本地存储代码包装在 try catch 块中,并在大小超出时在 catch 块中提醒用户。
2021-03-16 14:35:55
在 IE 中,您的代码在空间结束之前引发异常: window.localStorage.remainingSpace : 805692 | window.localStorage.getItem("DATA").length : 4194304 | JSON.stringify(localStorage).length : 4194315 | 我:22
2021-04-04 14:35:55
IE:ABORT_ERR:20 代码:22 消息:“QuotaExceededError” 名称:“QuotaExceededError”
2021-04-06 14:35:55
20-21 我想。如果您愿意,您可以自己运行测试。
2021-04-11 14:35:55

IE8remainingSpace为此目的实现了该属性:

alert(window.localStorage.remainingSpace);  // should return 5000000 when empty

不幸的是,这似乎在其他浏览器中不可用。但是我不确定他们是否实现了类似的东西。

@WmasterJ:我看到 IE 团队实际上提议将此(或类似的东西)包含在标准中(早在 2008 年):markmail.org/thread/ugzdcamtyftcyk6y
2021-03-16 14:35:55
@RuiLima,请注意,因为 javascript 中的字符使用了两个字节而不是一个字节,所以 5000000 个字符实际上占用了 10MB 的空间。似乎 IE 可能会报告剩余的字符数,而不是字节数,或者他们改变了对存储限制的看法。
2021-03-25 14:35:55
如果您希望 localStorage 溢出会引发异常,则这个剩余空间属性很重要:IE 不会抛出异常。因此,您需要在尝试保存到 localStorage 之前和之后检查此属性。如果大小没有改变,你就知道你已经超出了你的限制。
2021-03-28 14:35:55
这次IE是对的。很明显,这是必要的。
2021-04-03 14:35:55
我不明白这一点,微软表示:“localStorage 属性为域提供了持久存储区域。出于性能原因,它允许 Web 应用程序在客户端上存储近 10 MB 的用户数据,例如整个文档或用户的邮箱。 ” 但最后剩余空间返回 5000000 (?!?!) 为什么?!
2021-04-04 14:35:55

您可以使用以下行来准确计算此值,这里有一个 jsfiddle用于说明其用法

alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
George,该示例假定 UTF-8 字符集由大多数基于美国的 HTML 站点上的“Content-Type”元标记定义。如果你想考虑 unicode 支持,请看这里mathiasbynens.be/notes/javascript-unicode 或者为了快速修复这里是一个函数来解释 JS github.com/craniumslows/Countable/commit/ 中的unicode 支持 ...
2021-03-18 14:35:55
看起来您破坏了 JSFiddle,尽管您仍然可以在这里看到输出
2021-03-26 14:35:55
您的 jsfiddle 未在我的浏览器(mac/chrome)中加载。
2021-03-27 14:35:55
对于每个字符 8 个字节之类的东西,您不必乘以 8 吗?
2021-03-31 14:35:55
我正在使用此算法来确定 chrome 扩展的已用空间,但我记得读过另一个 SO 问题(现在忘记哪个),JS 使用 UTF-16 字符串而不是 UTF-8,因此,您必须加倍通过执行 string.length 获得的字节数。你知道这是不是真的吗?如果是这样,我将不得不更新我的代码...
2021-04-06 14:35:55

今天在测试时遇到了这个问题(超过了存储配额)并提出了一个解决方案。IMO,知道限制是什么以及我们所处的位置远不如实施一种功能性的方式来继续超出配额的存储value。

因此,与其尝试进行大小比较和容量检查,不如让我们在达到配额时做出react,将当前存储量减少三分之一,然后继续存储。如果所述还原失败,则停止存储。

set: function( param, val ) { 
    try{
        localStorage.setItem( param, typeof value == 'object' ? JSON.stringify(value) : value )
        localStorage.setItem( 'lastStore', new Date().getTime() )
    }
    catch(e){
      if( e.code === 22 ){
        // we've hit our local storage limit! lets remove 1/3rd of the entries (hopefully chronologically)
        // and try again... If we fail to remove entries, lets silently give up
        console.log('Local storage capacity reached.')

        var maxLength = localStorage.length
          , reduceBy = ~~(maxLength / 3);

        for( var i = 0; i < reduceBy; i++ ){
          if( localStorage.key(0) ){
            localStorage.removeItem( localStorage.key(0) );
          }
          else break;
        }

        if( localStorage.length < maxLength ){
          console.log('Cache data reduced to fit new entries. (' + maxLength + ' => ' + localStorage.length + ')');
          public.set( param, value );
        }
        else {
          console.log('Could not reduce cache size. Removing session cache setting from this instance.');
          public.set = function(){}
        }
      }
    }
}

这个函数存在于一个包装对象中,所以 public.set 只是调用它自己。现在我们可以添加到存储,而不必担心配额是多少或我们离它有多近。如果单个存储超过 1/3,配额大小就是此函数将停止剔除并退出存储的地方,此时,您无论如何都不应该缓存,对吗?