641

由于localStorage(当前)仅支持字符串作为值,并且为了做到这一点,对象需要在存储之前进行字符串化(存储为 JSON 字符串),因此是否存在关于值长度的定义限制。

有谁知道是否有适用于所有浏览器的定义?

4

12 回答 12

475

引用维基百科关于 Web Storage的文章:

Web 存储可以简单地视为对 cookie 的改进,提供更大的存储容量(在 Google Chrome ( https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh)、Mozilla Firefox中每个来源 10 MB和 Opera;Internet Explorer 中每个存储区域 10 MB)和更好的编程接口。

并且还引用了John Resig 的一篇文章[2007 年 1 月发布]:

储存空间

这意味着,使用 DOM 存储,您拥有的存储空间比对 Cookie 施加的典型用户代理限制要多得多。但是,提供的数量没有在规范中定义,也没有由用户代理有意义地广播。

如果您查看 Mozilla 源代码,我们可以看到 5120KB 是整个域的默认存储大小。与典型的 2KB cookie 相比,这为您提供了更多的工作空间。

但是,这个存储区域的大小可以由用户自定义(因此 5MB 的存储区域不是保证,也不是暗示)和用户代理(例如 Opera,可能只提供 3MB - 但只有时间会证明一切。 )

于 2010-06-07T12:12:55.480 回答
145

实际上 Opera 没有 5MB 的限制。当应用程序需要更多时,它会增加限制。用户甚至可以为域选择“无限存储”。

您可以自己轻松测试 localStorage 限制/配额

于 2010-07-15T21:24:43.077 回答
94

这是找出限制的简单脚本:

if (localStorage && !localStorage.getItem('size')) {
    var i = 0;
    try {
        // Test up to 10 MB
        for (i = 250; i <= 10000; i += 250) {
            localStorage.setItem('test', new Array((i * 1024) + 1).join('a'));
        }
    } catch (e) {
        localStorage.removeItem('test');
        localStorage.setItem('size', i - 250);            
    }
}

这是要点JSFiddle博客文章

该脚本将测试设置越来越大的文本字符串,直到浏览器抛出异常。此时它将清除测试数据并在 localStorage 中设置一个大小键,以千字节为单位存储大小。

于 2014-09-12T16:12:43.790 回答
40

找到可以存储的单个字符串的最大长度localStorage

此代码段将找到可以存储在localStorage每个域中的字符串的最大长度。

//Clear localStorage
for (var item in localStorage) delete localStorage[item];

window.result = window.result || document.getElementById('result');

result.textContent = 'Test running…';

//Start test
//Defer running so DOM can be updated with "test running" message
setTimeout(function () {

    //Variables
    var low = 0,
        high = 2e9,
        half;

    //Two billion may be a little low as a starting point, so increase if necessary
    while (canStore(high)) high *= 2;


    //Keep refining until low and high are equal
    while (low !== high) {
        half = Math.floor((high - low) / 2 + low);

        //Check if we can't scale down any further
        if (low === half || high === half) {
            console.info(low, high, half);
            //Set low to the maximum possible amount that can be stored 
            low = canStore(high) ? high : low;
            high = low;
            break;
        }


        //Check if the maximum storage is no higher than half
        if (storageMaxBetween(low, half)) {
            high = half;
            //The only other possibility is that it's higher than half but not higher than "high"
        } else {
            low = half + 1;
        }

    }

    //Show the result we found!
    result.innerHTML = 'The maximum length of a string that can be stored in localStorage is <strong>' + low + '</strong> characters.';

    //Functions
    function canStore(strLen) {
        try {
            delete localStorage.foo;
            localStorage.foo = Array(strLen + 1).join('A');
            return true;
        } catch (ex) {
            return false;
        }
    }


    function storageMaxBetween(low, high) {
        return canStore(low) && !canStore(high);
    }

}, 0);
<h1>LocalStorage single value max length test</h1>

<div id='result'>Please enable JavaScript</div>

请注意,字符串的长度在 JavaScript 中是有限的;如果您想查看localStorage不限于单个字符串时可以存储的最大数据量,您可以使用此答案中的代码

编辑: Stack Snippets don't support localStorage,所以这里是 JSFiddle 的链接

结果

Chrome (45.0.2454.101): 5242878 个字符
Firefox (40.0.1): 5242883 个字符
Internet Explorer (11.0.9600.18036)16386 122066122070 个字符

我在 Internet Explorer 中每次运行都会得到不同的结果。

于 2015-10-12T15:38:58.593 回答
27

不要假设 5MB 可用 - localStorage 容量因浏览器而异,最常见的值为 2.5MB、5MB 和无限制。来源:http ://dev-test.nemikor.com/web-storage/support-test/

于 2012-02-10T06:53:15.120 回答
19

您不希望将大对象字符串化到单个 localStorage 条目中。那将是非常低效的——每次一些细微的细节变化时,整个事情都必须被解析和重新编码。此外,JSON 不能处理对象结构中的多个交叉引用,并且会删除很多细节,例如构造函数、数组的非数字属性、稀疏条目中的内容等。

相反,您可以使用Rhaboo。它使用大量 localStorage 条目来存储大型对象,因此您可以快速进行小的更改。恢复的对象是保存对象的更准确的副本,API 非常简单。例如:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

顺便说一句,我写的。

于 2014-10-01T11:32:00.217 回答
17

我编写了这个以字节为单位测试 localStorage 大小的简单代码。

https://github.com/gkucmierz/Test-of-localStorage-limits-quota

const check = bytes => {
  try {
    localStorage.clear();
    localStorage.setItem('a', '0'.repeat(bytes));
    localStorage.clear();
    return true;
  } catch(e) {
    localStorage.clear();
    return false;
  }
};

Github 页面:

https://gkucmierz.github.io/Test-of-localStorage-limits-quota/

我在桌面 chrome、opera、firefox、brave 和 mobile chrome 上的结果相同,大约为 5Mbytes

在此处输入图像描述

小一半的结果是 safari ~2Mbytes

在此处输入图像描述

于 2020-05-03T22:43:54.370 回答
8

我已经将二进制测试压缩到我使用的这个函数中:

function getStorageTotalSize(upperLimit/*in bytes*/) {
    var store = localStorage, testkey = "$_test"; // (NOTE: Test key is part of the storage!!! It should also be an even number of characters)
    var test = function (_size) { try { store.removeItem(testkey); store.setItem(testkey, new Array(_size + 1).join('0')); } catch (_ex) { return false; } return true; }
    var backup = {};
    for (var i = 0, n = store.length; i < n; ++i) backup[store.key(i)] = store.getItem(store.key(i));
    store.clear(); // (you could iterate over the items and backup first then restore later)
    var low = 0, high = 1, _upperLimit = (upperLimit || 1024 * 1024 * 1024) / 2, upperTest = true;
    while ((upperTest = test(high)) && high < _upperLimit) { low = high; high *= 2; }
    if (!upperTest) {
        var half = ~~((high - low + 1) / 2); // (~~ is a faster Math.floor())
        high -= half;
        while (half > 0) high += (half = ~~(half / 2)) * (test(high) ? 1 : -1);
        high = testkey.length + high;
    }
    if (high > _upperLimit) high = _upperLimit;
    store.removeItem(testkey);
    for (var p in backup) store.setItem(p, backup[p]);
    return high * 2; // (*2 because of Unicode storage)
}

它还在测试前备份内容,然后恢复它们。

它是如何工作的:它将大小加倍,直到达到限制或测试失败。然后它存储低和高之间距离的一半,并每次减去/加上一半的一半(失败时减去,成功时加上);磨练成适当的价值。

upperLimit默认情况下为 1GB,并且仅限制在开始二进制搜索之前以指数方式向上扫描的距离。我怀疑这甚至需要改变,但我总是提前考虑。;)

在 Chrome 上:

> getStorageTotalSize();
> 10485762
> 10485762/2
> 5242881
> localStorage.setItem("a", new Array(5242880).join("0")) // works
> localStorage.setItem("a", new Array(5242881).join("0")) // fails ('a' takes one spot [2 bytes])

IE11、Edge 和 FireFox 也报告相同的最大大小(10485762 字节)。

于 2019-03-20T22:05:36.420 回答
6

我正在执行以下操作:

getLocalStorageSizeLimit = function () {

    var maxLength = Math.pow(2,24);
    var preLength = 0;
    var hugeString = "0";
    var testString;
    var keyName = "testingLengthKey";

    //2^24 = 16777216 should be enough to all browsers
    testString = (new Array(Math.pow(2, 24))).join("X");

    while (maxLength !== preLength) {
        try  {
            localStorage.setItem(keyName, testString);

            preLength = testString.length;
            maxLength = Math.ceil(preLength + ((hugeString.length - preLength) / 2));

            testString = hugeString.substr(0, maxLength);
        } catch (e) {
            hugeString = testString;

            maxLength = Math.floor(testString.length - (testString.length - preLength) / 2);
            testString = hugeString.substr(0, maxLength);
        }
    }

    localStorage.removeItem(keyName);

    maxLength = JSON.stringify(this.storageObject).length + maxLength + keyName.length - 2;

    return maxLength;
};
于 2014-06-16T21:28:27.120 回答
6

我真的很喜欢cdmckay 的回答,但是实时检查大小看起来并不好:它太慢了(对我来说是 2 秒)。这是改进的版本,速度更快,更准确,还可以选择误差有多大(默认250,000,误差越小 - 计算时间越长):

function getLocalStorageMaxSize(error) {
  if (localStorage) {
    var max = 10 * 1024 * 1024,
        i = 64,
        string1024 = '',
        string = '',
        // generate a random key
        testKey = 'size-test-' + Math.random().toString(),
        minimalFound = 0,
        error = error || 25e4;

    // fill a string with 1024 symbols / bytes    
    while (i--) string1024 += 1e16;

    i = max / 1024;

    // fill a string with 'max' amount of symbols / bytes    
    while (i--) string += string1024;

    i = max;

    // binary search implementation
    while (i > 1) {
      try {
        localStorage.setItem(testKey, string.substr(0, i));
        localStorage.removeItem(testKey);

        if (minimalFound < i - error) {
          minimalFound = i;
          i = i * 1.5;
        }
        else break;
      } catch (e) {
        localStorage.removeItem(testKey);
        i = minimalFound + (i - minimalFound) / 2;
      }
    }

    return minimalFound;
  }
}

去测试:

console.log(getLocalStorageMaxSize()); // takes .3s
console.log(getLocalStorageMaxSize(.1)); // takes 2s, but way more exact

这对于标准错误的工作速度要快得多;必要时也可以更准确。

于 2016-03-14T12:39:21.843 回答
6

您可以在现代浏览器中使用以下代码来有效地实时检查存储配额(总和已使用):

if ('storage' in navigator && 'estimate' in navigator.storage) {
        navigator.storage.estimate()
            .then(estimate => {
                console.log("Usage (in Bytes): ", estimate.usage,
                            ",  Total Quota (in Bytes): ", estimate.quota);
            });
}
于 2018-05-21T12:58:50.133 回答
4

由于这个原因,我开发了 Chrome(桌面浏览器)扩展并测试了本地存储的实际最大大小。

我的结果:

Ubuntu 18.04.1 LTS (64-bit)
Chrome 71.0.3578.98 (Official Build) (64-bit)
Local Storage content size 10240 KB (10 MB)

超过10240 KB使用量给我返回了错误:

未捕获的 DOMException:无法在“Storage”上执行“setItem”:设置“notes”的值超出了配额。

2020 年 10 月 23 日编辑

对于 Chrome 扩展可用的chrome.storageAPI。如果您在以下位置声明“存储”权限manifest.js

{
    "name": "My extension",
    ...
    "permissions": ["storage"],
    ...
}

您可以像这样访问它:

chrome.storage.local.QUOTA_BYTES // 5242880 (in bytes)
于 2019-04-18T16:23:04.783 回答