【问题标题】:Calculating usage of localStorage space计算本地存储空间的使用情况
【发布时间】:2011-03-02 21:53:52
【问题描述】:

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

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

【问题讨论】:

标签: javascript size storage local-storage capacity


【解决方案1】:

你可以用这个web storage support test测试你的浏览器

我在我的 android 平板电脑和 Windows 笔记本电脑上测试了 Firefox,并在 Windows 上测试了 Chromium 结果:

  1. Firefox(Windows):
  • localStorage:5120k 字符
  • sessionStorage:5120k 字符
  • globalStorage:*不支持
  1. Firefox(安卓):
  • localStorage:2560k 字符
  • sessionStorage:无限制(确切的测试运行高达 10240k 字符 == 20480k 字节)
  • globalStorage不支持
  1. Chromium(Windows):
  • localStorage:5120k 字符
  • sessionStorage:5120k 字符
  • globalStorage不支持

###更新 在 Google Chrome 版本 52.0.2743.116 m(64 位)上,5101k 字符的限制稍低。这意味着 max available 可能会在版本中发生变化。

【讨论】:

  • 你的意思是 5120k char
  • @Juribiyan 是的,我愿意。
【解决方案2】:
 try {
     var count = 100;
     var message = "LocalStorageIsNOTFull";
     for (var i = 0; i <= count; count + 250) {
         message += message;
         localStorage.setItem("stringData", message);
         console.log(localStorage);
         console.log(count);
     }

 }
 catch (e) {
     console.log("Local Storage is full, Please empty data");
     // fires When localstorage gets full
     // you can handle error here ot emply the local storage
 }

【讨论】:

    【解决方案3】:

    通过使用 JSON 方法将整个 localStorage 对象转换为 JSON 字符串,您也许可以得到一个大概的想法:

    JSON.stringify(localStorage).length
    

    我不知道它的字节精度如何,尤其是在使用其他对象时添加标记的几个字节 - 但我认为这比认为你只推送 28K 而不是做 280K 更好(反之亦然)。

    【讨论】:

    • 这实际上足够准确,可以使用。在 Chrome 14 上使用 localStorage 时,JSON.stringify(localStorage).length === 2636625 或 2.51448 MB,这已经足够接近 (dev-test.nemikor.com/web-storage/support-test)。与 try{} catch{} 一起使用,您就可以构建一个帮助类。
    • 请注意,正如您在链接的测试中指出的那样,这是一个字符大小,而不是字节:“JavaScript 中的字符串是 UTF-16,因此每个字符需要两个字节的内存。这个意味着虽然许多浏览器有 5 MB 的限制,但您只能存储 250 万个字符。”
    【解决方案4】:

    您可以使用下面的行来准确计算此值,here is a jsfiddle 用于说明其用途

    alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
    

    【讨论】:

    • 我正在使用此算法来确定 chrome 扩展的已用空间,但我记得读过另一个 SO 问题(现在忘记哪个问题了),JS 使用 UTF-16 字符串而不是 UTF-8,因此,您必须通过执行 string.length 将获得的字节数加倍。你知道这是不是真的?如果是这样,我将不得不更新我的代码......
    • 您的 jsfiddle 无法在我的浏览器 (mac/chrome) 中加载。
    • 看起来你破坏了 JSFiddle,虽然你仍然可以看到输出 here!
    • 每个字符的 8 个字节是否必须乘以 8 或类似的东西?
    • George,该示例假定大多数美国 HTML 网站上的“Content-Type”元标记所定义的 UTF-8 字符集。如果您想考虑 unicode 支持,请查看这里 mathiasbynens.be/notes/javascript-unicode 或者为了快速修复这里是一个函数来解释 JS 中的 unicode 支持 github.com/craniumslows/Countable/commit/…
    【解决方案5】:

    我需要实际模拟和测试我的模块在存储已满时会做什么,因此我需要在存储已满时获得接近的精度,而不是接受的答案,它会以 i 的速度失去该精度^2.

    这是我的脚本,当达到内存上限时,它应该始终产生 10 的精度,并且尽管进行了一些简单的优化,但相当快......编辑:我使脚本更好并且具有精确的精度:

    function fillStorage() {
        var originalStr = "1010101010";
        var unfold = function(str, times) {
            for(var i = 0; i < times; i++)
                str += str;
            return str;
        }
        var fold = function(str, times) {
            for(var i = 0; i < times; i++) {
                var mid = str.length/2;
                str = str.substr(0, mid);
            }
            return str;
        }
    
        var runningStr = originalStr;
        localStorage.setItem("filler", runningStr);
        while(true) {
            try {
                runningStr = unfold(runningStr, 1);
                console.log("unfolded str: ", runningStr.length)
                localStorage.setItem("filler", runningStr);
            } catch (err) {
                break;
            }
        }
    
        runningStr = fold(runningStr, 1);  
        var linearFill = function (str1) {
            localStorage.setItem("filler", localStorage.getItem("filler") + str1);
        }
        //keep linear filling until running string is no more...
        while(true) {
            try {
                linearFill(runningStr)
            } catch (err) {
                runningStr = fold(runningStr, 1);
                console.log("folded str: ", runningStr.length)
                if(runningStr.length == 0)
                    break;
            }
        }
    
        console.log("Final length: ", JSON.stringify(localStorage).length)
    }
    

    【讨论】:

      【解决方案6】:

      此函数获取确切可用/剩余的存储空间:

      我为localStorage做了一套有用的函数*here*

      http://jsfiddle.net/kzq6jgqa/3/

      function getLeftStorageSize() {
          var itemBackup = localStorage.getItem("");
          var increase = true;
          var data = "1";
          var totalData = "";
          var trytotalData = "";
          while (true) {
              try {
                  trytotalData = totalData + data;
                  localStorage.setItem("", trytotalData);
                  totalData = trytotalData;
                  if (increase) data += data;
              } catch (e) {
                  if (data.length < 2) break;
                  increase = false;
                  data = data.substr(data.length / 2);
              }
          }
          localStorage.setItem("", itemBackup);
      
          return totalData.length;
      }
      
      // Examples
      document.write("calculating..");
      var storageLeft = getLeftStorageSize();
      console.log(storageLeft);
      document.write(storageLeft + "");
      
      // to get the maximum possible *clear* the storage 
      localStorage.clear();
      var storageMax = getLeftStorageSize();
      

      注意,这不是很快,所以不要一直使用它。

      由此我还发现:Item-Name 将占用与其长度一样多的空间,Item-Value 也将占用与其长度一样多的空间。

      我获得的最大存储空间 - 大约 5M:

      • 5000000 个字符 - 边缘
      • 5242880 个字符 - Chrome
      • 5242880 个字符 - Firefox
      • 5000000 个字符 - IE

      您会在 fiddle 中找到一些注释掉的代码,以便在控制台中查看进度。

      花了我一些时间来制作,希望对你有帮助☺

      【讨论】:

        【解决方案7】:

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

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

        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
          • 消息:“无法在 'Storage' 上执行 'setItem':设置 'data' 的值超出了配额。”
          • 名称:“QuotaExceededError”

        Mozilla 火狐

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

        Safari

        • DOM 异常:
          • 代码:22
          • 消息:“QuotaExceededError:DOM 异常 22”
          • 名称:“QuotaExceededError”

        Internet Explorer、Edge(社区)

        • DOM 异常:
          • 代码:22
          • 消息:“QuotaExceededError”
          • 名称:“QuotaExceededError”

        我的解决方案

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


        编辑:删除添加的数据

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

        【讨论】:

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

        这可能对某人有所帮助。在 chrome 中,如果需要,可以要求用户允许使用更多磁盘空间:

        // Request Quota (only for File System API)  
        window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
          window.webkitRequestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler); 
        }, function(e) {
          console.log('Error', e); 
        });
        

        访问https://developers.google.com/chrome/whitepapers/storage#asking_more了解更多信息。

        【讨论】:

          【解决方案9】:

          希望我可以在评论中添加这个 - 没有足够的代表,抱歉。​​

          我进行了一些性能测试 - 期望 JSON.stringify(localStorage).length 在大型 localStorage 占用情况下是一项昂贵的操作。

          http://jsperf.com/occupied-localstorage-json-stringify-length

          确实如此 - 比跟踪您正在存储的内容要贵 50 倍,而且 localStorage 越全面,成本就会越低。

          【讨论】:

            【解决方案10】:

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

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

            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,则配额大小是此函数将停止剔除并退出存储的位置,此时,您不应该缓存,对吧?

            【讨论】:

              【解决方案11】:

              添加到浏览器测试结果:

              火狐 我=22。

              Safari 我的 Mac 上的 5.0.4 版没有挂起。错误为 Chrome。我=21。

              歌剧 告诉用户网站想要存储数据但没有足够的空间。用户可以拒绝请求,将限制增加到所需数量或其他几个限制,或将其设置为无限制。转到opera:webstorage 看看这条消息是否出现。我=20。抛出的错误与 Chrome 相同。

              IE9 标准模式 错误为 Chrome。我=22。

              IE8 标准模式下的 IE9 控制台消息“错误:没有足够的存储空间来完成此操作”。 i=22

              旧模式下的 IE9 对象错误。我=22。

              IE8 没有要测试的副本,但支持本地存储 (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)

              IE7 及以下 不支持本地存储。

              【讨论】:

                【解决方案12】:

                IE8 为此实现了remainingSpace 属性:

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

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

                【讨论】:

                • @WmasterJ:我看到 IE 团队实际上提议将此(或类似的东西)包含在标准中(早在 2008 年):markmail.org/thread/ugzdcamtyftcyk6y
                • 这次IE是对的。显然这是需要的。
                • 我不明白,微软说:“localStorage 属性为域提供持久存储区域。它允许 Web 应用程序存储近 10 MB 的用户数据,例如整个文档或用户的邮箱,出于性能原因在客户端上。”但最后剩余空间返回 5000000(?!?!)为什么?!
                • @RuiLima,请注意,由于 javascript 中的字符占用了两个字节而不是一个字节,因此 5000000 个字符实际上占用了 10MB 的空间。似乎 IE 可能会报告剩余的字符,而不是字节,或者他们改变了对存储限制的看法。
                • 如果您期望 localStorage 溢出引发异常,则此剩余空间属性很重要:IE 不会引发异常。因此,您需要在尝试保存到 localStorage 之前和之后检查此属性。如果尺寸没有改变,你就知道你已经超出了限制。
                猜你喜欢
                • 2014-09-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-03-27
                • 2011-01-17
                • 2017-02-24
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多