83

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

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

4

12 回答 12

74

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

JSON.stringify(localStorage).length

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

于 2011-06-13T03:32:03.677 回答
56

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

为了最大化它,我使用了这个小脚本:

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
    • 消息:“QuotaExceededError:DOM 异常 22”
    • 名称:“配额超出错误”

Internet Explorer、Edge(社区)

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

我的解决方案

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


编辑:删除添加的数据

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

于 2010-06-12T02:32:53.300 回答
26

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

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

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

于 2010-06-12T01:45:05.017 回答
16

您可以使用下面的行来准确计算这个值,这里是一个 jsfiddle来说明它的使用

alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
于 2012-04-13T03:43:58.247 回答
9

今天在测试(超过存储配额)时遇到了这个问题并提出了一个解决方案。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,则配额大小是此函数将停止剔除并退出存储的位置,此时,您不应该缓存,对吧?

于 2013-09-26T21:41:07.363 回答
5

添加到浏览器测试结果:

火狐 i=22。

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

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

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

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

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

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

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

于 2011-09-06T09:18:55.380 回答
2

希望我可以在评论中添加这个 - 没有足够的代表,对不起。

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

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

确实如此 - 比跟踪您正在存储的内容贵 50 倍左右,并且更全面的 localStorage 变得更糟。

于 2014-09-16T13:52:39.020 回答
2

您可以使用此网络存储支持测试来测试您的浏览器

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

  1. 火狐(Windows):
  • 本地存储: 5120k字符
  • 会话存储: 5120k字符
  • 全球存储:*不支持
  1. 火狐(安卓):
  • 本地存储: 2560k字符
  • sessionStorage:无限制(确切测试运行高达 10240k 字符 == 20480k 字节)
  • 全局存储不支持
  1. (Windows):
  • 本地存储: 5120k字符
  • 会话存储: 5120k字符
  • 全局存储不支持

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

于 2014-10-15T12:13:09.140 回答
2

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

我为 localStorage *在这里做了一套有用的功能*

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 个字符 - 铬
  • 5242880 个字符 - 火狐
  • 5000000 个字符 - IE

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

花了我一些时间制作,希望这有助于☺</p>

于 2015-12-12T20:26:50.220 回答
1

我需要实际模拟和测试我的模块在存储已满时会做什么,因此我需要在存储已满时获得一个接近的精度,而不是接受的答案,它以 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)
}
于 2016-01-27T19:23:11.363 回答
1
 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
 }
于 2017-10-13T12:59:26.380 回答
0

这可能会帮助某人。在 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了解更多信息。

于 2015-01-23T16:14:44.313 回答