Як знайти розмір localStorage


117

Зараз я розробляю сайт, який використовуватиме локальну сховище HTML5. Я прочитав усе про обмеження розміру для різних браузерів. Однак я нічого не бачив, як дізнатися поточний розмір екземпляра localStorage. Це питання вказує на те, що JavaScript не має вбудованого способу відображення розміру для певної змінної. Чи має у localStorage властивість розміру пам'яті, яку я не бачив? Чи є простий спосіб зробити це, що мені не вистачає?

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


Відповіді:


219

Виконайте цей фрагмент у консолі 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, тому що char у javascript зберігається як UTF-16 (займає 2 байти)

PPS повинен працювати як в Chrome, так і в Firefox.


8
Вставте це в консоль, щоб побачити загальну кількість: var t = 0; for (var x in localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Генрі

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

2
@Serge, ця відповідь найбільше проголосувала, отже розміщуємо тут var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir

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
Це лише
властивість

чи обмеження 5 мб на сайті чи загальне для всіх сайтів?
divyenduz

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

2
Зауважте, що властивість localStorage.remainingSpace повертає залишкову кількість символів UTF-16, дозволених для об’єкта зберігання. НЕ залишився розмір у байтах. Довідка
Міхір

14

Ось простий приклад того, як це зробити і має працювати з кожним браузером

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

вам не потрібен * 8 десь там?
Джордж Мауер

1
Залежить від набору символів (тобто utf8 тощо), який не враховується
jas-

Це дає розмір у байтах чи у бітах?
JamesTheAwesomeDude

6
Цей приклад неправильно передбачає, що localStorage має однаковий фіксований межа у 5 МБ (5 * 1024 * 1024) у кожному браузері.
Віктор

Це відповідно до специфікації, викладеної w3c.
jas-

13

Сподіваюся, це допоможе комусь.

Оскільки Jas- example на jsfiddle для мене не працює, я придумав це рішення. (дякую Сергію Селецькому та Шураву за їхні шматочки, які я використав у коді нижче)

Нижче наведена функція, яка може бути використана для перевірки, скільки місця доступно для 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 ~ 1130ms 5Mb
  • Firefox 20.0 (бета-версія 20.0) розбив обоє
  • Chrome 25.0.1364.169 ~ 22250ms / 5Mb
  • Native (ідентифікується як Safari 4.0 / Webkit534.30) ~ 995ms / 5Mb

iPhone 4s iOS 6.1.3

  • Safari ~ 520ms / 5Mb
  • Як HomeApp ~ 525ms / 5Mb
  • iCab ~ 710ms / 5mb

MacBook Pro OSX 1.8.3 (пам'ять Core 2 Duo 2.66 8Gb)

  • Safari 6.0.3 ~ 105ms / 5Mb
  • Chrome 26.0.1410.43 ~ 3400ms / 5Mb
  • Firefox 20,0 300150ms (!) / 10Mb (після скарги на те, що сценарій працює до довгого)

iPad 3 iOS 6.1.3

  • Safari ~ 430ms / 5Mb
  • iCab ~ 595ms / 5mb

Windows 7 -64b (Core 2 Duo 2,93 6Gb пам'яті)

  • Safari 5,1,7 ~ 80ms / 5Mb
  • Chrome 26.0.1410.43 ~ 1220ms / 5Mb
  • Firefox 20,0 228500 мс (!) / 10 Мб (після скарги на те, що сценарій працює до довгого)
  • IE9 ~ 17900ms /9.54Mb (якщо якісь console.logs є в коді, не працює, поки DevTools не буде відкрито)
  • Opera 12.15 ~ 4212ms /3.55Mb (це коли вибрано 5Mb, але Opera чудово запитує, чи хочемо ми збільшити кількість lS, на жаль, вона виходить з ладу, якщо тест проводився кілька разів поспіль)

Виграйте 8 (під паралелями 8)

  • IE10 ~ 7850ms /9.54Mb

Чудові експерименти. Однак я знайшов array.forEach()у вашому коді, оскільки я знаю, що його немає в IE, чи реалізуєте ви його самостійно? Як ви вимірюєте його внесок у загальну затримку?
Пісня Evi

Дякую, я можу повторити їх, оскільки минуло деякий час від початкових тестів. Що стосується forEach(). Ні, я сам цього не реалізував, я використав запас Array.prototype.forEach(). За інформацією Mozilla Developer Network, яка називається MDN від IE9, вона має вбудовану підтримку.
Якуб Гадковський

Дякую. Мої знання потрібно оновити. Пізніше я використаю Array.prototype.forEach()якомога більше, якщо мій проект не підтримує ранні версії IE.
Пісня Evi

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

IE10 Rocks .. І все-таки найшвидший браузер для завантаження Chrome :)
Руслан Абузант

11

Ви можете отримати поточний розмір даних локального зберігання за допомогою функції Blob. Це може не працювати в старих веб-переглядачах, перевірте підтримку new Blobта Object.values()каніузу.

Приклад:

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. В обох випадках я отримав абсолютно однакову максимальну локальну довжину зберігання. Отже, розмір символів Blob не впливає на обмеження локального зберігання. Ось чому 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

Я вирішив цю проблему - створити функції для пошуку використовуваного простору та залишків у Local Storage, а потім функцію, яка викликає ці функції для визначення максимального простору зберігання.

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

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 чи щось подібне?
Міхір

1

По мірі специфікації кожен символ рядка - 16 біт.

Але огляд хромом (Налаштування> Налаштування вмісту> Файли cookie та дані веб-сайту) показує нам, що для ініціювання localStorage потрібно 3 кБ (накладні розміри)

І збережений розмір даних відповідає цьому співвідношенню (точно до 1 кБ)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

де 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

Найкращий спосіб отримати заповнений обсяг пам’яті - переглянути налаштування сайту (скажімо, якщо ви зберегли зображення в локальному сховищі). Принаймні в хромі, ви можете бачити кількість використаних байтів (тобто: 1222 байти). Однак найкращі способи побачити заповнені локальні сховища з js вже були згадані вище, тому використовуйте їх.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.