计算localStorage空间的使用


79

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

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



JavaScript / HTML5 localStorage有用的功能:stackoverflow.com/q/34245593/4339170
CoderPi 2015年

Answers:


72

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

JSON.stringify(localStorage).length

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


4
实际上,这足够准确了。在Chrome 14上,当localStorage达到最大值时,JSON.stringify(localStorage).length === 2636625或2.51448 MB,足够接近(dev-test.nemikor.com/web-storage/support-test)。与try {} catch {}结合使用,您已经足够构建一个辅助类。
Christopher

13
请注意,正如您链接的测试中指出的那样,这是一个字符大小而不是字节大小:“ JavaScript中的字符串为UTF-16,因此每个字符都需要两个字节的内存。这意味着,尽管许多浏览器都使用5 MB的限制,您只能存储2.5 M个字符。”
Mortimer

51

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

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

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");

由此我得到了以下信息:

谷歌浏览器

  • DOMException:
    • 码:22
    • 消息:“无法在“存储”上执行“ setItem”:设置“数据”的值超出了配额。”
    • 名称:“ QuotaExceededError”

火狐浏览器

  • DOMException:
    • 码:1014
    • 消息:“已达到永久存储的最大大小”
    • 名称:“ NS_ERROR_DOM_QUOTA_REACHED”

苹果浏览器

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

Internet Explorer,Edge(社区)

  • DOMException:
    • 码:22
    • 消息:“ QuotaExceededError”
    • 名称:“ QuotaExceededError”

我的解决方案

到目前为止,我的解决方案是每次用户保存任何内容时都添加一个额外的呼叫。如果发现异常,我会告诉他们它们的存储容量已用完。


编辑:删除添加的数据

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


很好,i在每种情况下达到此目标的价值是什么?
artlung 2010年

我认为是20-21。您可以根据需要自己运行测试。
JeroenEijkhof

IE:ABORT_ERR:20代码:22消息:“ QuotaExceededError”名称:“ QuotaExceededError”
Rui Lima

在IE中,您的代码在空格结束之前引发异常:window.localStorage.remainingSpace:805692 | window.localStorage.getItem(“ DATA”)。length:4194304 | JSON.stringify(localStorage).length:4194315 | 我:22
Rui Lima)

好的,那么我可以将本地存储代码包装在try catch块中,并在超出大小的catch块中警告用户。
Nirus

26

IE8remainingSpace为此实现了该属性:

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

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


1
@WmasterJ:我看到IE团队实际上建议将此标准(或类似内容)包含在标准中(早在2008年):markmail.org/thread/ugzdcamtyftcyk6y
丹尼尔·瓦萨洛

45
这次IE是正确的。显然这是必需的。
JeroenEijkhof

我不明白这一点,微软说:“ localStorage属性为域提供了持久的存储区域。出于性能原因,它允许Web应用程序在客户端上存储近10 MB的用户数据,例如整个文档或用户的邮箱。 ” 但是最后,remainingSpace返回5000000(?!?!)为什么?
Rui Lima

3
@RuiLima,请注意,因为javascript中的字符占用了两个字节而不是一个字节,所以5000000个字符实际上占用了10MB的空间。好像IE可能正在报告剩余字符而不是字节,或者他们改变了对存储限制的想法。
Ishmael Smyrnow

1
如果您期望localStorage的溢出会引发异常,则此剩余空间属性非常重要:IE不会抛出异常。因此,您需要在尝试保存到localStorage之前和之后检查此属性。如果大小没有更改,您就知道您已经超出了限制。
安迪2014年

15

您可以使用下面的行来准确计算该值,这是一个使用jsfiddle来说明其用法的示例

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

我正在使用此算法来确定chrome扩展的已用空间,但我记得读过另一个SO问题(现在忘记了哪个问题),即JS使用UTF-16字符串而不是UTF-8,因此,您必须加倍通过执行string.length获得的字节数。你知道那是真的吗?如果是这样,我将不得不更新我的代码...
Adam Tuttle

1
您的jsfiddle无法在我的浏览器(mac / chrome)中加载。
贾斯汀

看起来您已经打破了JSFiddle,尽管您仍然可以在此处看到输出!
c24w

您是否不必将8乘以每个字符8个字节或类似的字符?
乔治·莫尔2014年

乔治(George),该示例假定在美国大多数HTML网站上由“ Content-Type”元标记定义的UTF-8字符集。如果您希望考虑对unicode的支持,请在此处查看mathiasbynens.be/notes/javascript-unicode 或此处的快速修复功能是在JSgithub.com/craniumslows/Countable/commit/…中
jas -

9

今天在测试(超过存储配额)时就考虑了这一点,并提出了一个解决方案。国际海事组织,知道极限是什么以及我们之间的关系远比实施一种功能性方法来继续超出配额继续存储的价值要小得多。

因此,与其尝试进行大小比较和容量检查,不如在达到配额后做出反应,将当前存储空间减少三分之一,然后恢复存储。如果上述还原失败,请停止存储。

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,则配额大小是该函数将停止淘汰并退出存储的位置,在这一点上,您无论如何都不应该进行缓存,对吗?


5

要添加到浏览器测试结果:

Firefox i = 22。

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

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

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

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

IE9在较旧模式下会出现 对象错误。i = 22。

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

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


3

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

我在Android平板电脑和Windows笔记本电脑上都测试了Firefox,仅在Windows结果上测试了Chromium

  1. Firefox(Windows):

    • localStorage:5120k字符
    • sessionStorage:5120k字符
    • localStorage:*不支持
  2. Firefox(Android):

    • localStorage:2560k字符
    • sessionStorage:无限制(精确测试最多运行10240k char == 20480k字节)
    • localStorage不支持
  3. (Windows):

    • localStorage:5120k字符
    • sessionStorage:5120k字符
    • localStorage不支持

更新资料

在Google Chrome版本52.0.2743.116 m(64位)上,5101k字符的限制稍低一些。这意味着可用的最大值可能会在版本中更改。


您的意思是5120 k字符
Juribiyan

@Juribiyan是的。
Morteza Tourani

2

希望我可以在评论中添加此内容-代表人数不足,对不起。

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

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

的确如此-与跟踪存储内容相比要贵50倍,而更糟的localStorage变得更糟。


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个字符-Firefox
  • 5000000个字符-IE

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

花了我一些时间来做,希望这会有所帮助


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
 }

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)
}

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了解更多信息。

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.