Как узнать размер localStorage


118

В настоящее время я разрабатываю сайт, который будет использовать localStorage HTML5. Я читал все об ограничениях по размеру для разных браузеров. Однако я ничего не видел о том, как узнать текущий размер экземпляра localStorage. Этот вопрос, кажется, указывает на то, что JavaScript не имеет встроенного способа отображения размера данной переменной. Есть ли у localStorage свойство размера памяти, которого я не видел? Есть ли простой способ сделать это, что мне не хватает?

Мой сайт предназначен для того, чтобы пользователи могли вводить информацию в «автономном» режиме, поэтому очень важно иметь возможность предупреждать их, когда хранилище почти заполнено.


Ответы:


222

Выполните этот фрагмент в консоли JavaScript (однострочная версия):

var _lsTotal=0,_xLen,_x;for(_x in localStorage){ if(!localStorage.hasOwnProperty(_x)){continue;} _xLen= ((localStorage[_x].length + _x.length)* 2);_lsTotal+=_xLen; console.log(_x.substr(0,50)+" = "+ (_xLen/1024).toFixed(2)+" KB")};console.log("Total = " + (_lsTotal / 1024).toFixed(2) + " KB");

Один и тот же код в нескольких строках для чтения

var _lsTotal = 0,
    _xLen, _x;
for (_x in localStorage) {
    if (!localStorage.hasOwnProperty(_x)) {
        continue;
    }
    _xLen = ((localStorage[_x].length + _x.length) * 2);
    _lsTotal += _xLen;
    console.log(_x.substr(0, 50) + " = " + (_xLen / 1024).toFixed(2) + " KB")
};
console.log("Total = " + (_lsTotal / 1024).toFixed(2) + " KB");

или добавьте этот текст в поле «расположение» закладки для удобства использования

javascript: var x, xLen, log=[],total=0;for (x in localStorage){if(!localStorage.hasOwnProperty(x)){continue;} xLen =  ((localStorage[x].length * 2 + x.length * 2)/1024); log.push(x.substr(0,30) + " = " +  xLen.toFixed(2) + " KB"); total+= xLen}; if (total > 1024){log.unshift("Total = " + (total/1024).toFixed(2)+ " MB");}else{log.unshift("Total = " + total.toFixed(2)+ " KB");}; alert(log.join("\n")); 

PS Фрагменты обновляются по запросу в комментарии. Теперь в расчет входит длина самого ключа. Каждая длина умножается на 2, потому что символ в javascript хранится как UTF-16 (занимает 2 байта)

PPS Должен работать как в Chrome, так и в Firefox.


8
Вставьте это в консоль, чтобы увидеть результат: var t = 0; for (var x в localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + «КБ»);
Генри

5
@Micah Javascript внутренне использует UTF16, поэтому, поскольку каждый символ хранится в виде двух байтов, вам нужно умножить количество символов на два, чтобы получить фактическое используемое пространство. (Вы, наверное, уже обнаружили это, но я подумал, что стоит отметить здесь, потому что у кого-то еще есть такой же вопрос)
Ребека

2
@Serge, за этот ответ проголосовало больше всего, поэтому отправляю здесь var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Михир

17
Вот модифицированная версия, которая также учитывает NaN:var _lsTotal = 0, _xLen, _x; for (_x in localStorage) { _xLen = (((localStorage[_x].length || 0) + (_x.length || 0)) * 2); _lsTotal += _xLen; console.log(_x.substr(0, 50) + " = " + (_xLen / 1024).toFixed(2) + " KB") }; console.log("Total = " + (_lsTotal / 1024).toFixed(2) + " KB");
Марио Саннум

1
В букмарклете есть ошибка. Вы используете подчеркнутые переменные в основном коде и обычные имена в букмарклете. Одиночное подчеркивание _xломает его. Просто удалите подчеркивание.
Soul Reaver

46

Исходя из того, что сказал @Shourav выше, я написал небольшую функцию, которая должна точно захватить все ваши localStorageключи (для текущего домена) и вычислить комбинированный размер, чтобы вы точно знали, сколько памяти занимает ваш localStorageобъект:

var localStorageSpace = function(){
        var allStrings = '';
        for(var key in window.localStorage){
            if(window.localStorage.hasOwnProperty(key)){
                allStrings += window.localStorage[key];
            }
        }
        return allStrings ? 3 + ((allStrings.length*16)/(8*1024)) + ' KB' : 'Empty (0 KB)';
    };

Мой вернулся: "30.896484375 KB"


1
Спасибо @tennisgent. Моя работала для IE11, FF> 26, а также для Chrome.
Akki922234

18

IE имеет remainingSpace свойство объекта хранения. Остальные браузеры в настоящее время не имеют аналогов.

Я считаю, что объем дискового пространства по умолчанию составляет 5 МБ, хотя лично я его не тестировал.


1
Это свойство только IE
jas-

ограничение в 5 МБ на сайт или в целом для всех сайтов?
divyenduz

@divyenduz на сайт, я думаю
Адам

2
Обратите внимание, что свойство localStorage.remainingSpace возвращает оставшееся количество символов UTF-16, разрешенных для объекта хранения. НЕ оставшийся размер в байтах. Ссылка
Mihir

14

Вот простой пример того, как это сделать, и он должен работать с каждым браузером.

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

тебе не нужен * 8 где-то там?
Джордж Мауэр

1
Зависит от набора символов (например, utf8 и т. Д.),
Который

Это дает размер в байтах или в битах?
JamesTheAwesomeDude

6
В этом примере неверно предполагается, что localStorage имеет одинаковый фиксированный лимит в 5 МБ (5 * 1024 * 1024) в каждом браузере.
Виктор

Это согласно спецификации, выдвинутой w3c.
jas-

13

Надеюсь, это кому-то поможет.

Поскольку пример Jas на jsfiddle у меня не работает, я придумал это решение. (спасибо Serge Seletskyy и Shourav за их биты, которые я использовал в коде ниже)

Ниже приведена функция, с помощью которой можно проверить, сколько места доступно для localStorage и (если какие-либо ключи уже находятся в lS) сколько места осталось.

Это небольшая грубая сила, но она работает почти во всех браузерах ... кроме Firefox. Что ж, в настольном FF для завершения требуется время (4-5 минут), а на Android он просто вылетает.

Под функцией находится краткий обзор тестов, которые я провел в разных браузерах на разных платформах. Наслаждайтесь!

function testLocalStorage() {
    var timeStart = Date.now();
    var timeEnd, countKey, countValue, amountLeft, itemLength;
    var occupied = leftCount = 3; //Shurav's comment on initial overhead
//create localStorage entries until localStorage is totally filled and browser issues a warning.
    var i = 0;
    while (!error) {
        try {
//length of the 'value' was picked to be a compromise between speed and accuracy, 
// the longer the 'value' the quicker script and result less accurate. This one is around 2Kb 
            localStorage.setItem('testKey' + i, '11111111112222222222333333333344444444445555555555666661111111111222222222233333333334444444444555555555566666');
        } catch (e) {
            var error = e;
        }
        i++;
    }
//if the warning was issued - localStorage is full.
    if (error) {
//iterate through all keys and values to count their length
        for (var i = 0; i < localStorage.length; i++) {
            countKey = localStorage.key(i);
            countValue = localStorage.getItem(localStorage.key(i));
            itemLength = countKey.length + countValue.length;
//if the key is one of our 'test' keys count it separately
            if (countKey.indexOf("testKey") !== -1) {
                leftCount = leftCount + itemLength;
            }
//count all keys and their values
            occupied = occupied + itemLength;
        }
        ;
//all keys + values lenght recalculated to Mb
        occupied = (((occupied * 16) / (8 * 1024)) / 1024).toFixed(2);
//if there are any other keys then our 'testKeys' it will show how much localStorage is left
        amountLeft = occupied - (((leftCount * 16) / (8 * 1024)) / 1024).toFixed(2);
//iterate through all localStorage keys and remove 'testKeys'
        Object.keys(localStorage).forEach(function(key) {
            if (key.indexOf("testKey") !== -1) {
                localStorage.removeItem(key);
            }
        });

    }
//calculate execution time
    var timeEnd = Date.now();
    var time = timeEnd - timeStart;
//create message
    var message = 'Finished in: ' + time + 'ms \n total localStorage: ' + occupied + 'Mb \n localStorage left: ' + amountLeft + "Mb";
//put the message on the screen
    document.getElementById('scene').innerText = message; //this works with Chrome,Safari, Opera, IE
//document.getElementById('scene').textContent = message;  //Required for Firefox to show messages
}

И, как было обещано выше, несколько тестов в разных браузерах:

GalaxyTab 10.1

  • Maxthon Pad 1.7 ~ 1130 мс 5 МБ
  • Firefox 20.0 (Beta 20.0) вылетел как
  • Chrome 25.0.1364.169 ~ 22250 мс / 5 МБ
  • Собственный (идентифицируется как Safari 4.0 / Webkit534.30) ~ 995 мс / 5 МБ

iPhone 4s iOS 6.1.3

  • Safari ~ 520 мс / 5 Мб
  • Как HomeApp ~ 525 мс / 5 МБ
  • iCab ~ 710 мс / 5 МБ

MacBook Pro OSX 1.8.3 (Core 2 Duo 2,66 8 ГБ памяти)

  • Safari 6.0.3 ~ 105 мс / 5 Мб
  • Chrome 26.0.1410.43 ~ 3400 мс / 5 МБ
  • Firefox 20.0 300150 мс (!) / 10 МБ (после жалобы на долгую работу скрипта)

iPad 3 iOS 6.1.3

  • Safari ~ 430 мс / 5 Мб
  • iCab ~ 595 мс / 5 МБ

Windows 7 -64b (Core 2 Duo 2,93 6 ГБ памяти)

  • Safari 5.1.7 ~ 80 мс / 5 Мб
  • Chrome 26.0.1410.43 ~ 1220 мс / 5 МБ
  • Firefox 20.0 228500 мс (!) / 10 МБ (после жалобы на слишком долгую работу скрипта)
  • IE9 ~ 17900 мс / 9,54 Мб (если в коде есть console.logs, не работает, пока не откроются DevTools)
  • Opera 12.15 ~ 4212 мс / 3,55 МБ (это когда выбрано 5 МБ, но Opera красиво спрашивает, хотим ли мы увеличить количество lS, к сожалению, он вылетает, если тест проводится несколько раз подряд)

Победа 8 (в параллелях 8)

  • IE10 ~ 7850 мс / 9,54 МБ

Отличные эксперименты. Однако я нашел array.forEach()в вашем коде, поскольку я знаю, что его нет в IE, вы реализуете самостоятельно? Как вы измеряете его вклад в общую задержку?
Evi Song

Спасибо, я мог бы переделать их, так как прошло некоторое время с первоначальных тестов. Что касается forEach(). Нет, сам не реализовал, использовал сток Array.prototype.forEach(). Согласно Mozilla Developer Network, также известной как MDN из IE9, он имеет встроенную поддержку.
Якуб Гадковски

Спасибо. Мои знания нуждаются в обновлении. Позже я буду использовать Array.prototype.forEach()как можно больше, если мой проект не будет поддерживать ранние версии IE.
Evi Song

Код можно сделать значительно быстрее (~ 2500 мс в Firefox, ~ 700 мс в Chrome): разделить whileцикл на две части, первую, как в stackoverflow.com/a/3027249/1235394, которая заполняет localStorage экспоненциально растущими порциями данных, а затем вторая часть с небольшие фрагменты фиксированного размера для полного заполнения хранилища. Тестовая страница: jsfiddle.net/pqpps3tk/1
Виктор

IE10 Rocks .. Тем не менее, самый быстрый браузер для загрузки Chrome :)
Руслан Абузант

11

Вы можете получить текущий размер данных локального хранилища с помощью функции Blob. Это может не работать в старых браузерах, проверьте поддержку new Blobи Object.values()на caniuse.

Пример:

return new Blob(Object.values(localStorage)).size;

Object.values ​​() превращает объект localStorage в массив. Blob превращает массив в необработанные данные.


3
Я думаю, Blobчто не ограничивает строковую кодировку UTF-16, поэтому это может быть самый надежный метод. new Blob(['X']).size;= 1, тогда как new Blob(['☃']).size(U + 2603 / персонаж снеговика) ==> 3. Решения, основанные на этом String.prototype.length, не принимают это во внимание (имеют дело с «персонажами»), тогда как квоты / ограничения хранилища, вероятно, учитывают (имеют дело с байтами), и я мог представить это приводило к неожиданностям, например, при хранении неанглийских символов / символов ASCII.
iX3

Я использовал ответ Джеда, который вычисляет размер localStorage с длиной строк для тестирования решения Blob в Chrome и FF. В первом тесте я заполнил localStorage знаком «1». во втором тесте я заполнил localStorage знаком «☃», который имеет больший размер в объекте Blob. В обоих случаях я получил одинаковую максимальную длину localStorage. Таким образом, размер символа Blob не влияет на ограничение localStorage. Вот почему Blob не следует использовать для этой цели.
Винсенте,

6

Вы можете рассчитать местное хранилище следующими способами:

function sizeofAllStorage(){  // provide the size in bytes of the data currently stored
  var size = 0;
  for (i=0; i<=localStorage.length-1; i++)  
  {  
  key = localStorage.key(i);  
  size += lengthInUtf8Bytes(localStorage.getItem(key));
  }  
  return size;
}

function lengthInUtf8Bytes(str) {
  // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
  var m = encodeURIComponent(str).match(/%[89ABab]/g);
  return str.length + (m ? m.length : 0);
}

console.log(sizeofAllStorage());

Наконец, размер в байтах будет зарегистрирован в браузере.


4

Я бы использовал код @tennisgen, который получает все и считает содержимое, но я считаю сами ключи:

var localStorageSpace = function(){
        var allStrings = '';
        for(var key in window.localStorage){
            allStrings += key;
            if(window.localStorage.hasOwnProperty(key)){
                allStrings += window.localStorage[key];
            }
        }
        return allStrings ? 3 + ((allStrings.length*16)/(8*1024)) + ' KB' : 'Empty (0 KB)';
    };

3

Я решил эту проблему так, чтобы создать функции для определения используемого и оставшегося пространства в локальном хранилище, а затем функцию, которая вызывает эти функции для определения максимального объема хранилища.

function getUsedSpaceOfLocalStorageInBytes() {
    // Returns the total number of used space (in Bytes) of the Local Storage
    var b = 0;
    for (var key in window.localStorage) {
        if (window.localStorage.hasOwnProperty(key)) {
            b += key.length + localStorage.getItem(key).length;
        }
    }
    return b;
}

function getUnusedSpaceOfLocalStorageInBytes() {
    var maxByteSize = 10485760; // 10MB
    var minByteSize = 0;
    var tryByteSize = 0;
    var testQuotaKey = 'testQuota';
    var timeout = 20000;
    var startTime = new Date().getTime();
    var unusedSpace = 0;
    do {
        runtime = new Date().getTime() - startTime;
        try {
            tryByteSize = Math.floor((maxByteSize + minByteSize) / 2);
            localStorage.setItem(testQuotaKey, new Array(tryByteSize).join('1'));
            minByteSize = tryByteSize;
        } catch (e) {
            maxByteSize = tryByteSize - 1;
        }
    } while ((maxByteSize - minByteSize > 1) && runtime < timeout);

    localStorage.removeItem(testQuotaKey);

    if (runtime >= timeout) {
        console.log("Unused space calculation may be off due to timeout.");
    }

    // Compensate for the byte size of the key that was used, then subtract 1 byte because the last value of the tryByteSize threw the exception
    unusedSpace = tryByteSize + testQuotaKey.length - 1;
    return unusedSpace;
}

function getLocalStorageQuotaInBytes() {
    // Returns the total Bytes of Local Storage Space that the browser supports
    var unused = getUnusedSpaceOfLocalStorageInBytes();
    var used = getUsedSpaceOfLocalStorageInBytes();
    var quota = unused + used;
    return quota;
}

Array.join - убийца производительности, лучше используйте String.repeat там, где это возможно (то есть везде, кроме IE)
pkExec 01

2

В дополнение к ответу @ serge, который получил здесь наибольшее количество голосов, необходимо учитывать размер ключей. Код ниже добавит размер ключей, хранящихся вlocalStorage

var t = 0; 
for (var x in localStorage) { 
    t += (x.length + localStorage[x].length) * 2; 
} 
console.log((t / 1024) + " KB");

Я обнаружил , что Firefox возвращает undefinedдля элемента lengthв некоторых случаях, поэтому я добавил условное добавления: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin

@camilokawerin, этого не должно быть, если в хранилище не сохранено неопределенное значение, потому что String - единственный тип, который поддерживается с помощью localStorage, а String действительно имеет свойство Length. Не могли бы вы опубликовать пример на jsfiddle или что-то подобное?
Mihir

1

Согласно спецификации, каждый символ строки составляет 16 бит.

Но проверка с помощью Chrome (Настройки> Настройки контента> Файлы cookie и данные сайта) показывает нам, что запуск localStorage занимает 3 КБ (размер накладных расходов).

И размер хранимых данных следует этому соотношению (с точностью до 1 КБ)
3 + ((localStorage.x.length * 16) / (8 * 1024)) КБ

где localStorage.x - строка вашего хранилища.


0

// Память занята как ключом, так и значением, поэтому обновленный код.

var jsonarr=[];
var jobj=null;
for(x in sessionStorage) // Iterate through each session key
{
    jobj={}; 
    jobj[x]=sessionStorage.getItem(x); //because key will also occupy some memory
    jsonarr.push(jobj);
    jobj=null;
}
//https://developer.mozilla.org/en/docs/Web/JavaScript/Data_structures 
//JavaScript's String type is used to represent textual data. It is a set of "elements" of 16-bit unsigned integer values. 
var size=JSON.stringify(jsonarr).length*2; //16-bit that's why multiply by 2
var arr=["bytes","KB","MB","GB","TB"]; // Define Units
var sizeUnit=0;
while(size>1024){ // To get result in Proper Unit
    sizeUnit++;
    size/=1024;
}
alert(size.toFixed(2)+" "+arr[sizeUnit]);

0

Да, этот вопрос задавали лет 10 назад. Но для тех, кто интересуется (например, я, поскольку я создаю автономный текстовый редактор, который сохраняет данные в локальном хранилище) и не умеет программировать, вы можете использовать что-то простое, например:

var warning = 1;
var limit = 2000000; //2 million characters, not really taking in account to bytes but for tested ammounts of characters stored
setInterval(function() {
    localStorage["text"] = document.getElementById("editor").innerHTML; //gets text and saves it in local storage under "text"
    if(localStorage["text"].length > limit && warning == 1){
            alert("Local Storage capacity has been filled"); 
            warning = 2; //prevent a stream of alerts
    }
}, 1000);
//setInterval function saves and checks local storage

Лучший способ получить заполненный объем хранилища - это просмотреть настройки сайта (например, если вы сохранили изображение в локальном хранилище). По крайней мере, в Chrome вы можете увидеть количество использованных байтов (например, 1222 байта). Однако лучшие способы увидеть заполненное локальное хранилище с помощью js уже упоминались выше, поэтому используйте их.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.