Javascript 计算localStorage空间的使用情况
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3027142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculating usage of localStorage space
提问by JeroenEijkhof
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.
我正在使用 Bespin 编辑器和 HTML5 的 localStorage 创建一个应用程序。它在本地存储所有文件并帮助处理语法,使用 JSLint 和其他一些 CSS 和 HTML 解析器来帮助用户。
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.
我想计算使用了多少 localStorage 限制以及实际使用了多少。今天这可能吗?我在想不要简单地计算存储的位。但话又说回来,我不确定还有什么是我无法衡量自己的。
采纳答案by JeroenEijkhof
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"
- DOM 异常:
- 代码:22
- 消息:“无法在‘存储’上执行‘setItem’:设置‘数据’的值超出了配额。”
- 名称:“配额超出错误”
Mozilla Firefox
火狐浏览器
- DOMException:
- code: 1014
- message: "Persistent storage maximum size reached"
- name: "NS_ERROR_DOM_QUOTA_REACHED"
- DOM 异常:
- 代码:1014
- 消息:“已达到持久存储的最大大小”
- 名称:“NS_ERROR_DOM_QUOTA_REACHED”
Safari
苹果浏览器
- DOMException:
- code: 22
- message: "QuotaExceededError: DOM Exception 22"
- name: "QuotaExceededError"
- DOM 异常:
- 代码:22
- 消息:“配额超出错误:DOM 异常 22”
- 名称:“配额超出错误”
Internet Explorer, Edge(community)
Internet Explorer、Edge(社区)
- DOMException:
- code: 22
- message: "QuotaExceededError"
- name: "QuotaExceededError"
- DOM 异常:
- 代码:22
- 消息:“配额超出错误”
- 名称:“配额超出错误”
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 DATAitem that was set originally. The change is reflected above by using the removeItem()function.
我忘了提到要真正起作用,您需要删除DATA最初设置的项目。更改通过使用removeItem()函数反映在上面。
回答by Morgon
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 方法将整个 localStorage 对象转换为 JSON 字符串来大致了解:
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).
我不知道它的字节精度有多高,尤其是如果您使用其他对象时添加的标记的几个字节 - 但我认为这比认为您只推 28K 而不是做 280K(或副 -反之)。
回答by Daniel Vassallo
IE8 implements the remainingSpaceproperty for this purpose:
IE8remainingSpace为此目的实现了该属性:
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.
不幸的是,这似乎在其他浏览器中不可用。但是我不确定他们是否实现了类似的东西。
回答by jas-
You can use the below line to accurately calculate this value and here is a jsfiddlefor illustration of its use
您可以使用以下行来准确计算此值,这里有一个 jsfiddle来说明其用法
alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
回答by Shiboe
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.
今天在测试时遇到了这个问题(超过了存储配额)并提出了一个解决方案。IMO,知道限制是什么以及我们所处的位置远不如实施一种功能性的方式来继续超出配额的存储价值。
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?
这个函数存在于一个包装对象中,所以 public.set 只是调用它自己。现在我们可以添加到存储,而不必担心配额是多少或我们离它有多近。如果单个存储超过 1/3,配额大小就是此函数将停止剔除并退出存储的地方,此时,您无论如何都不应该缓存,对吗?
回答by user535673
To add to the browser test results:
添加到浏览器测试结果:
Firefoxi=22.
火狐i=22。
SafariVersion 5.0.4 on my Mac didn't hang. Error as Chrome. i=21.
我的 Mac 上的Safari版本 5.0.4 没有挂起。错误为 Chrome。我=21。
OperaTells 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.
Opera告诉用户该网站想要存储数据但没有足够的空间。用户可以拒绝请求,将限制提高到所需数量或其他几个限制,或将其设置为无限制。转到opera:webstorage 说是否出现此消息。我=20。抛出的错误与 Chrome 相同。
IE9 standards modeError as Chrome. i=22.
IE9 标准模式错误为 Chrome。我=22。
IE9 in IE8 standards modeConsole message "Error: Not enough storage is available to complete this operation". i=22
IE8 标准模式下的 IE9控制台消息“错误:没有足够的存储空间来完成此操作”。我=22
IE9 in older modesobject error. i=22.
旧模式下的 IE9对象错误。我=22。
IE8Don'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)
IE8没有要测试的副本,但支持本地存储 (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)
IE7 and belowDoesn't support local storage.
IE7 及以下不支持本地存储。
回答by Morteza Tourani
You can test your browser with this web storage support test
您可以使用此Web 存储支持测试来测试您的浏览器
I tested Firefoxon both my android tablet and windows laptop and Chromiumjust on windows results:
我在我的 android 平板电脑和 windows 笔记本电脑上测试了Firefox,仅在 windows上测试了Chromium结果:
Firefox(windows):
- localStorage: 5120k char
- sessionStorage: 5120k char
- localStorage: *not supported
Firefox(android):
- localStorage: 2560k char
- sessionStorage: Unlimited (exactly test runs up to 10240k char == 20480k byte)
- localStorage: not supported
Chromium(windows):
- localStorage: 5120k char
- sessionStorage: 5120k char
- localStorage: not supported
火狐(Windows):
- 本地存储:5120k 字符
- sessionStorage的:5120k字符
- 本地存储:*不支持
火狐(安卓):
- 本地存储:2560k 字符
- sessionStorage:无限制(确切测试运行高达 10240k 字符 == 20480k 字节)
- 本地存储:不支持
铬(窗户):
- 本地存储:5120k 字符
- sessionStorage的:5120k字符
- 本地存储:不支持
Update
更新
On Google Chrome Version 52.0.2743.116 m (64-bit) limits where a little bit lower on 5101kcharacters. This means max available may change in versions.
在 Google Chrome 版本 52.0.2743.116 m(64 位)上,5101k字符限制稍低。这意味着最大可用版本可能会发生变化。
回答by SashaK
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.
我运行了一些性能测试 - 期望 JSON.stringify(localStorage).length 在大型 localStorage 占用率上是一个昂贵的操作。
http://jsperf.com/occupied-localstorage-json-stringify-length
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.
确实如此 - 比跟踪您存储的内容贵大约 50 倍,并且越完整的 localStorage 变得更糟。
回答by CoderPi
This function gets the exactstorage available / left:
此函数获取可用/剩余的确切存储空间:
I made a suite of useful functions for localStorage *here*
我为 localStorage *这里做了一套有用的函数*
http://jsfiddle.net/kzq6jgqa/3/
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.
有了这个,我还发现:Item-Name 将占用与其长度一样多的空间,Item-Value 也将占用与其长度一样多的空间。
Maximum storage I got - all about 5M:
我得到的最大存储空间 - 大约 5M:
- 5000000 chars - Edge
- 5242880 chars - Chrome
- 5242880 chars - Firefox
- 5000000 chars - IE
- 5000000 个字符 - 边缘
- 5242880 个字符 - 铬
- 5242880 个字符 - Firefox
- 5000000 个字符 - IE
You will find some out-commented code in the fiddle to see the progress in the console.
您会在 fiddle 中找到一些注释掉的代码,以在控制台中查看进度。
Took me some time to make, hope this helps ?
花了我一些时间来制作,希望这有帮助吗?
回答by balthatrix
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.
我需要实际模拟和测试我的模块在存储已满时将执行的操作,因此我需要在存储已满时获得接近的精度,而不是公认的答案,这会以 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:
这是我的脚本,当达到内存上限时,它应该总是产生 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)
}

