Javascript localStorage 值的最大大小是多少?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2989284/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:48:34  来源:igfitidea点击:

What is the max size of localStorage values?

javascripthtmllocal-storage

提问by Codekie

Since localStorage(currently) only supports strings as values, and in order to do that the objects need to be stringified (stored as JSON-string) before they can be stored, is there a defined limitation regarding the length of the values.

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

Does anyone know if there is a definition which applies to all browsers?

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

采纳答案by Daniel Vassallo

Quoting from the Wikipedia article on Web Storage:

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

Web storage can be viewed simplistically as an improvement on cookies, providing much greater storage capacity (10 MB per origin in Google Chrome(https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh), Mozilla Firefox, and Opera; 10 MB per storage area in Internet Explorer) and better programmatic interfaces.

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

And also quoting from a John Resig article[posted January 2007]:

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

Storage Space

It is implied that, with DOM Storage, you have considerably more storage space than the typical user agent limitations imposed upon Cookies. However, the amount that is provided is not defined in the specification, nor is it meaningfully broadcast by the user agent.

If you look at the Mozilla source code we can see that 5120KB is the default storage size for an entire domain. This gives you considerably more space to work with than a typical 2KB cookie.

However, the size of this storage area can be customized by the user(so a 5MB storage area is not guaranteed, nor is it implied) and the user agent (Opera, for example, may only provide 3MB - but only time will tell.)

储存空间

这意味着,使用 DOM 存储,您拥有比典型的用户代理限制强加在 Cookie 上的更多的存储空间。然而,提供的数量没有在规范中定义,也没有被用户代理有意义地广播。

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

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

回答by Artemy Tregubenko

Actually Opera doesn't have 5MB limit. It offers to increase limit as applications requires more. User can even choose "Unlimited storage" for a domain.

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

You can easily test localStorage limits/quotayourself.

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

回答by cdmckay

Here's a straightforward script for finding out the limit:

这是一个用于找出限制的简单脚本:

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

Here's the gist, JSFiddleand blog post.

这是要点JSFiddle博客文章

The script will test setting increasingly larger strings of text until the browser throws and exception. At that point it'll clear out the test data and set a size key in localStorage storing the size in kilobytes.

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

回答by user2428118

Find the maximum length of a single string that can be stored in localStorage

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

This snippet will find the maximum length of a String that can be stored in localStorageper domain.

此代码段将查找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>

Note that the length of a string is limited in JavaScript; if you want to view the maximum amount of data that can be stored in localStoragewhen not limited to a single string, you can use the code in this answer.

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

Edit:Stack Snippets don't support localStorage, so here is a link to JSFiddle.

编辑:Stack Snippets 不支持localStorage,所以这里有一个指向 JSFiddle 的链接

Results

结果

Chrome (45.0.2454.101):5242878 characters
Firefox (40.0.1):5242883 characters
Internet Explorer (11.0.9600.18036): 16386122066122070 characters

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

I get different results on each run in Internet Explorer.

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

回答by Behnam Mohammadi

Mobile browsers:

手机浏览器:

Browser    | Chrome    | Android Browser    | Firefox     | iOS Safari
Version    | 40        | 4.3                | 34          | 6-8
Available  | 10MB      | 2MB                | 10MB        | 5MB

Desktop browsers:

桌面浏览器:

Browser    | Chrome   | Opera    | Firefox    | Safari      | IE
Version    | 40       | 27       | 34         | 6-8         | 9-11
Available  | 10MB     | 10MB     | 10MB       | 5MB         | 10MB

Reference Link

参考链接

回答by tagawa

Don't assume 5MB is available - localStorage capacity varies by browser, with 2.5MB, 5MB and unlimited being the most common values. Source: http://dev-test.nemikor.com/web-storage/support-test/

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

回答by Adrian May

You don't want to stringify large objects into a single localStorage entry. That would be very inefficient - the whole thing would have to be parsed and re-encoded every time some slight detail changes. Also, JSON can't handle multiple cross references within an object structure and wipes out a lot of details, e.g. the constructor, non-numerical properties of arrays, what's in a sparse entry, etc.

您不想将大对象串成单个 localStorage 条目。那将是非常低效的——每次发生一些细微的细节变化时,都必须对整个事情进行解析和重新编码。此外,JSON 无法处理对象结构中的多个交叉引用,并抹去了很多细节,例如构造函数、数组的非数字属性、稀疏条目中的内容等。

Instead, you can use Rhaboo. It stores large objects using lots of localStorage entries so you can make small changes quickly. The restored objects are much more accurate copies of the saved ones and the API is incredibly simple. E.g.:

相反,您可以使用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');

BTW, I wrote it.

BTW,我写的。

回答by smnbbrv

I really like cdmckay's answer, but it does not really look good to check the size in a real time: it is just too slow (2 seconds for me). This is the improved version, which is way faster and more exact, also with an option to choose how big the error can be (default 250,000, the smaller error is - the longer the calculation is):

我真的很喜欢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;
  }
}

To test:

去测试:

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

This works dramatically faster for the standard error; also it can be much more exact when necessary.

对于标准误差,这显着更快;必要时它也可以更准确。

回答by Itay Merchav

I'm doing the following:

我正在做以下事情:

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

回答by James Wilkins

I've condensed a binary test into this function that I use:

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

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

It also backs up the contents before testing, then restores them.

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

How it works: It doubles the size until the limit is reached or the test fails. It then stores half the distance between low and high and subtracts/adds a half of the half each time (subtract on failure and add on success); honing into the proper value.

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

upperLimitis 1GB by default, and just limits how far upwards to scan exponentially before starting the binary search. I doubt this will even need to be changed, but I'm always thinking ahead. ;)

upperLimit默认情况下是 1GB,并且在开始二分搜索之前只限制向上扫描多远。我怀疑这甚至需要改变,但我总是提前考虑。;)

On Chrome:

在 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, and FireFox also report the same max size (10485762 bytes).

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