计算本地存储空间的使用情况

发布于 2024-09-05 13:01:35 字数 215 浏览 5 评论 0原文

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

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

I am creating an app using the Bespin editor and HTML5's localStorage. It stores all files locally and helps with grammar, uses JSLint and some other parsers for CSS and HTML to aid the user.

I want to calculate how much of the localStorage limit has been used and how much there actually is. Is this possible today? I was thinking for not to simply calculate the bits that are stored. But then again I'm not sure what more is there that I can't measure myself.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

不疑不惑不回忆 2024-09-12 13:01:35

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

JSON.stringify(localStorage).length

我不知道它的字节精度如何,特别是如果您是添加标记的几个字节使用额外的对象 - 但我认为这比认为你只推 28K 而做 280K 更好(反之亦然)。

You may be able to get an approximate idea by using the JSON methods to turn the whole localStorage object to a JSON string:

JSON.stringify(localStorage).length

I don't know how byte-accurate it would be, especially with the few bytes of added markup if you're using additional objects - but I figure it's better than thinking you're only pushing 28K and instead doing 280K (or vice-versa).

一曲爱恨情仇 2024-09-12 13:01:35

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

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

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

从中我得到了以下信息:

Google Chrome

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

Mozilla Firefox

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

Safari

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

Internet Explorer、Edge(社区)

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

我的解决方案

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


编辑:删除添加的数据

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

I didn't find a universal way to get the remaining limit on the browsers I needed, but I did find out that when you do reach the limit there is an error message that pops up. This is of-course different in each browser.

To max it out I used this little script:

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

From that I got this information:

Google Chrome

  • DOMException:
    • code: 22
    • message: "Failed to execute 'setItem' on 'Storage': Setting the value of 'data' exceeded the quota."
    • name: "QuotaExceededError"

Mozilla Firefox

  • DOMException:
    • code: 1014
    • message: "Persistent storage maximum size reached"
    • name: "NS_ERROR_DOM_QUOTA_REACHED"

Safari

  • DOMException:
    • code: 22
    • message: "QuotaExceededError: DOM Exception 22"
    • name: "QuotaExceededError"

Internet Explorer, Edge (community)

  • DOMException:
    • code: 22
    • message: "QuotaExceededError"
    • name: "QuotaExceededError"

My solution

So far my solution is to add an extra call each time the user would save anything. And if the exception is caught then I would tell them that they are running out of storage capacity.


Edit: Delete the added data

I forgot to mention that for this to actually work you would need to delete the DATA item that was set originally. The change is reflected above by using the removeItem() function.

隱形的亼 2024-09-12 13:01:35

IE8 实现了 remainingSpace用于此目的的 属性:

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

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

IE8 implements the remainingSpace property for this purpose:

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

Unfortunately it seems that this is not available in the other browsers. However I am not sure if they implement something similar.

南城追梦 2024-09-12 13:01:35

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

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

You can use the below line to accurately calculate this value and here is a jsfiddle for illustration of its use

alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
庆幸我还是我 2024-09-12 13:01:35

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

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

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,此函数将停止剔除并退出存储,此时,您无论如何都不应该进行缓存,对吗?

Ran into this today while testing (exceeding storage quota) and whipped up a solution. IMO, knowing what the limit is and where we are in relation is far less valuable than implementing a functional way to continue storing beyond the quota.

Thus, rather than trying to do size comparisons and capacity checks, lets react when we've hit the quota, reduce our current storage by a third, and resume storing. If said reduction fails, stop storing.

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

This function lives within a wrapper object, so public.set simply calls itself. Now we can add to storage and not worry what the quota is or how close we are too it. If a single store is exceeding 1/3rd the quota size is where this function will stop culling and quit storing, and at that point, you shouldn't be caching anyways, right?

奈何桥上唱咆哮 2024-09-12 13:01:35

添加到浏览器测试结果:

Firefox
我=22。

野生动物园
我的 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 和下面
不支持本地存储。

To add to the browser test results:

Firefox
i=22.

Safari
Version 5.0.4 on my Mac didn't hang. Error as Chrome. i=21.

Opera
Tells the user that the website wants to store data but doesn't have enough space. The user can reject the request, up the limit to the amount required or to several other limits, or set it to unlimited. Go to opera:webstorage to say whether this message appears or not. i=20. Error thrown is same as Chrome.

IE9 standards mode
Error as Chrome. i=22.

IE9 in IE8 standards mode
Console message "Error: Not enough storage is available to complete this operation". i=22

IE9 in older modes
object error. i=22.

IE8
Don't have a copy to test, but local storage is supported (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)

IE7 and below
Doesn't support local storage.

天荒地未老 2024-09-12 13:01:35

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

我运行了一些性能测试 - 期望 JSON.stringify(localStorage).length 在大量 localStorage 占用时成为昂贵的操作。

确实如此 - 比跟踪您存储的内容要贵大约 50 倍,而且 localStorage 越满,情况就越糟。

Wish I could add this in a comment - not enough rep, sorry.

I ran some perf tests - expecting JSON.stringify(localStorage).length to be an expensive op at large localStorage occupancy.

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

It is indeed so - about 50x more expensive than keeping track of what you're storing, and gets worse the fuller localStorage gets.

甜妞爱困 2024-09-12 13:01:35

此函数获取可用/剩余的精确存储:

我为 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 个字符 - Edge
  • 5242880 个字符 - Chrome
  • 5242880 个字符 - Firefox
  • 5000000 个字符 - IE

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

我花了一些时间制作,希望这会有所帮助 ☺

This function gets the exact storage available / left:

I made a suite of useful functions for 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();

Note, that this is not very quick, so don't use it all the time.

With this I also found out that: the Item-Name will take up as much space as its length, the Item-Value will also take up as much space as their length.

Maximum storage I got - all about 5M:

  • 5000000 chars - Edge
  • 5242880 chars - Chrome
  • 5242880 chars - Firefox
  • 5000000 chars - IE

You will find some out-commented code in the fiddle to see the progress in the console.

Took me some time to make, hope this helps ☺

情徒 2024-09-12 13:01:35

网络存储支持测试来测试您的浏览器

您可以使用我测试过 我的 Android 平板电脑和 Windows 笔记本电脑以及 Chromium 仅在 Windows 上
结果:

  1. Firefox(Windows):
  • localStorage:5120k 字符
  • sessionStorage:5120k 字符
  • globalStorage:*不支持
  1. Firefox(android):
  • localStorage: 2560k char
  • sessionStorage: 无限制(精确测试运行最多 10240k 字符 == 20480k 字节)
  • 全局存储不支持
  1. Chromium(Windows):
  • localStorage:5120k char
  • sessionStorage:5120k char
  • globalStorage不支持

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

You can test your browser with this web storage support test

I tested Firefox on both my android tablet and windows laptop and Chromium just on windows
results:

  1. Firefox(windows):
  • localStorage: 5120k char
  • sessionStorage: 5120k char
  • globalStorage: *not supported
  1. Firefox(android):
  • localStorage: 2560k char
  • sessionStorage: Unlimited (exactly test runs up to 10240k char == 20480k byte)
  • globalStorage: not supported
  1. Chromium(windows):
  • localStorage: 5120k char
  • sessionStorage: 5120k char
  • globalStorage: not supported

###Update
On Google Chrome Version 52.0.2743.116 m (64-bit) limits where a little bit lower on 5101k characters. This means max available may change in versions.

时光倒影 2024-09-12 13:01:35

我需要实际模拟和测试我的模块在存储已满时将执行的操作,因此我需要在存储已满时获得接近的精度,而不是接受的答案,后者会以 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)
}

I needed to actually simulate and test what my module will do when storage is full, so I needed to get a close precision on when the storage is full, rather than the accepted answer, which loses that precision at a rate of i^2.

Here's my script, which should always produce a precision of 10 on when memory cap is reached, and fairly quickly despite having some easy optimizations... EDIT: I made the script better and with an exact precision:

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)
}
昨迟人 2024-09-12 13:01:35
 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
 }
 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
 }
忘你却要生生世世 2024-09-12 13:01:35

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

This might help somebody. In chrome is possible to ask the user to allow to use more disk space if needed:

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

Visit https://developers.google.com/chrome/whitepapers/storage#asking_more for more info.

疯了 2024-09-12 13:01:35

如果本地存储不可用,此脚本将返回 false,或者将本地存储中的确切可用空间返回到最接近的字符,无论浏览器是否抛出错误,或者在本地存储已满时只是不向本地存储添加任何内容。

var localstorageavail;
function localstoragetest(remaining) {
  if (typeof(Storage) !== "undefined") {
    localstorageavail = true;
    var usedspace = JSON.stringify(localStorage).length;
    if (remaining == true) {
      var unusedspace = 0, data = "m", adddata, stored = 0;
        for (adddata = "m";;) {
          try { 
            localStorage.setItem("UN", data);
            if (stored < JSON.stringify(localStorage).length) {
              stored = JSON.stringify(localStorage).length;
              adddata += adddata;
              data += adddata;
            }
            else throw "toolong";
          } catch(e) {
          if (adddata == "m") break;
          else adddata = "m"; 
          data += adddata;
        }
      }
      var totalspace = JSON.stringify(localStorage).length;
      unusedspace = totalspace - usedspace;
      localStorage.removeItem("UN");
      alert("Space Used Calculated: " + usedspace + " " + "\nUnused space: " + unusedspace + "\nSpace Used according to browser: " + JSON.stringify(localStorage).length)
    }  
  } else {
//    alert("Sorry! No Web Storage support..");
    localstorageavail = false;
  }
  if (localstorageavail == false) return localstorageavail;
  else return unusedspace;
}
localstoragetest(true);

This script will return false if local storage is not available or return exact available space in local storage to the nearest character, regardless of if the browser throws an error or simply doesn't add anything to local storage when local storage is full.

var localstorageavail;
function localstoragetest(remaining) {
  if (typeof(Storage) !== "undefined") {
    localstorageavail = true;
    var usedspace = JSON.stringify(localStorage).length;
    if (remaining == true) {
      var unusedspace = 0, data = "m", adddata, stored = 0;
        for (adddata = "m";;) {
          try { 
            localStorage.setItem("UN", data);
            if (stored < JSON.stringify(localStorage).length) {
              stored = JSON.stringify(localStorage).length;
              adddata += adddata;
              data += adddata;
            }
            else throw "toolong";
          } catch(e) {
          if (adddata == "m") break;
          else adddata = "m"; 
          data += adddata;
        }
      }
      var totalspace = JSON.stringify(localStorage).length;
      unusedspace = totalspace - usedspace;
      localStorage.removeItem("UN");
      alert("Space Used Calculated: " + usedspace + " " + "\nUnused space: " + unusedspace + "\nSpace Used according to browser: " + JSON.stringify(localStorage).length)
    }  
  } else {
//    alert("Sorry! No Web Storage support..");
    localstorageavail = false;
  }
  if (localstorageavail == false) return localstorageavail;
  else return unusedspace;
}
localstoragetest(true);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文