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

有人知道是否有一个适用于所有浏览器的定义吗?


当前回答

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

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,仅限制在开始二分查找之前以指数方式向上扫描的距离。我怀疑这种情况是否需要改变,但我总是未雨绸缪。;)

铬:

> 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字节)。

其他回答

我真的很喜欢cdmckay的答案,但它并不真的看起来很好,实时检查大小:它太慢了(对我来说2秒)。这是改进的版本,它更快,更准确,也有一个选项来选择误差的大小(默认为250000,误差越小-计算时间越长):

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

对于标准错误,这工作得快得多;而且,在必要的时候,它可以更加精确。

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

这个代码片段将找到每个域可以存储在localStorage中的String的最大长度。

//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中可以存储的最大数据量,而不限于单个字符串,则可以使用此答案中的代码。

编辑:堆栈片段不支持localStorage,所以这里有一个到JSFiddle的链接。

结果

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

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

我正在做以下事情:

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

    // Original used this.storageObject in place of localStorage.  I can only guess the goal is to check the size of the localStorage with everything but the testString given that maxLength is then added.
    maxLength = JSON.stringify(localStorage).length + maxLength + keyName.length - 2;

    return maxLength;
};

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

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

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