Jak sprawdzić rozmiar localStorage


118

Obecnie tworzę witrynę, która będzie korzystać z localStorage HTML5. Przeczytałem wszystko o ograniczeniach rozmiaru dla różnych przeglądarek. Jednak nie widziałem nic, jak sprawdzić bieżący rozmiar instancji localStorage.To pytanie wydaje się wskazywać, że JavaScript nie ma wbudowanego sposobu pokazywania rozmiaru dla danej zmiennej. Czy localStorage ma właściwość rozmiaru pamięci, której nie widziałem? Czy jest na to łatwy sposób, którego mi brakuje?

Moja witryna ma umożliwiać użytkownikom wprowadzanie informacji w trybie „offline”, więc możliwość ostrzeżenia, gdy pamięć jest prawie pełna, jest bardzo ważna.


Odpowiedzi:


222

Wykonaj ten fragment w konsoli JavaScript (wersja jednowierszowa):

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

Ten sam kod w wielu wierszach do czytania

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

lub dodaj ten tekst w polu „lokalizacja” zakładki dla wygodnego użycia

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 Snippets są aktualizowane zgodnie z prośbą w komentarzu. Teraz obliczenia obejmują długość samego klucza. Każda długość jest mnożona przez 2, ponieważ znak w javascript jest przechowywany jako UTF-16 (zajmuje 2 bajty)

PPS powinien działać zarówno w przeglądarce Chrome, jak i Firefox.


8
Wklej to w konsoli, aby zobaczyć sumę: var t = 0; for (var x in localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Henry

5
@Micah Javascript używa wewnętrznie UTF16, więc ponieważ każdy znak jest przechowywany jako dwa bajty, należy pomnożyć liczbę znaków przez dwa, aby uzyskać rzeczywistą ilość zajętego miejsca. (Prawdopodobnie już to odkryłeś, ale pomyślałem, że warto to tutaj odnotować, bo ktoś inny ma to samo pytanie)
Rebecka

2
@Serge, ta odpowiedź jest najczęściej głosowana, dlatego zamieszczam tutaj var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir

17
Oto zmodyfikowana wersja, która uwzględnia również 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");
Mario Sannum

1
W bookmarklecie jest błąd. Używasz podkreślonych zmiennych w głównym kodzie i normalnych nazw w bookmarklet. Pojedyncze podkreślenie _xprzerywa to. Po prostu usuń podkreślenie.
Soul Reaver

46

Wychodząc z tego, co @Shourav powiedział powyżej, napisałem małą funkcję, która powinna dokładnie pobrać wszystkie localStorageklucze (dla bieżącej domeny) i obliczyć łączny rozmiar, abyś wiedział dokładnie, ile pamięci zajmuje twój localStorageobiekt:

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

Mój wrócił: "30.896484375 KB"


1
Dzięki @tennisgent. Mój działał dla IE11, FF> 26, a także dla Chrome.
Akki922234

18

IE ma właściwość pozostałej przestrzeni obiektu Storage. Inne przeglądarki nie mają obecnie odpowiedników.

Uważam, że domyślna ilość miejsca to 5MB, chociaż osobiście tego nie testowałem.


1
To jest jedyna własność IE
jas-

jest limit 5 MB na witrynę czy ogólnie dla wszystkich witryn?
divyenduz

@divyenduz na stronę, jak sądzę
Adam

2
Należy zauważyć, że właściwość localStorage.remainingSpace zwraca pozostałą liczbę znaków UTF-16 dozwolonych dla obiektu pamięci. NIE pozostały rozmiar w bajtach. Odniesienie
Mihir

14

Oto prosty przykład, jak to zrobić i powinien działać z każdą przeglądarką

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

czy nie potrzebujesz gdzieś tam * 8?
George Mauer

1
Zależy od zestawu znaków (np. Utf8 itp.),
Którego

Czy to podaje rozmiar w bajtach czy w bitach?
JamesTheAwesomeDude

6
W tym przykładzie niepoprawnie założono, że localStorage ma ten sam ustalony limit w 5 MB (5 * 1024 * 1024) w każdej przeglądarce.
Victor,

Jest to zgodne ze specyfikacją przedstawioną przez w3c.
jas-

13

Mam nadzieję, że to komuś pomoże.

Ponieważ przykład Jas- na jsfiddle u mnie nie działa, wymyśliłem takie rozwiązanie. (podziękowania dla Serge Seletskyy i Shourav za ich bity, których użyłem w poniższym kodzie)

Poniżej znajduje się funkcja, której można użyć do sprawdzenia, ile miejsca jest dostępne dla localStorage i (jeśli jakiekolwiek klucze są już w lS), ile miejsca pozostało.

To trochę brutalna siła, ale działa w prawie każdej przeglądarce ... poza Firefoksem. Cóż, w przypadku FF na komputery stacjonarne ukończenie go zajmuje wieki (4-5 minut), a na Androidzie po prostu ulega awarii.

Pod funkcją znajduje się krótkie podsumowanie testów, które wykonałem w różnych przeglądarkach na różnych platformach. Cieszyć się!

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
}

I zgodnie z obietnicą powyżej, niektóre testy w różnych przeglądarkach:

GalaxyTab 10.1

  • Maxthon Pad 1,7 ~ 1130 ms 5 Mb
  • Firefox 20.0 (Beta 20.0) rozbił oba
  • Chrome 25.0.1364.169 ~ 22250 ms / 5 Mb
  • Natywna (identyfikowana jako Safari 4.0 / Webkit534.30) ~ 995 ms / 5 Mb

iPhone 4s iOS 6.1.3

  • Safari ~ 520 ms / 5 Mb
  • Jako aplikacja HomeApp ~ 525 ms / 5 Mb
  • iCab ~ 710 ms / 5 MB

MacBook Pro OSX 1.8.3 (Core 2 Duo 2,66 8 Gb pamięci)

  • Safari 6.0.3 ~ 105 ms / 5 Mb
  • Chrome 26.0.1410.43 ~ 3400 ms / 5 Mb
  • Firefox 20.0 300150ms (!) / 10Mb (po narzekaniu, że skrypt działa zbyt długo)

iPad 3 iOS 6.1.3

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

Windows 7 - 64b (pamięć Core 2 Duo 2,93 6Gb)

  • Safari 5.1.7 ~ 80 ms / 5 Mb
  • Chrome 26.0.1410.43 ~ 1220 ms / 5 Mb
  • Firefox 20.0 228500ms (!) / 10Mb (po narzekaniu, że skrypt działa zbyt długo)
  • IE9 ~ 17900ms /9,54Mb (jeśli w kodzie znajdują się jakiekolwiek console.logs, nie działa, dopóki nie zostaną otwarte DevTools)
  • Opera 12.15 ~ 4212ms / 3.55Mb (to jest gdy jest wybrane 5Mb, ale Opera ładnie pyta, czy chcemy zwiększyć ilość lS, niestety zawiesza się, jeśli test jest przeprowadzany kilka razy z rzędu)

Wygraj 8 (pod paralelami 8)

  • IE10 ~ 7850 ms / 9,54 Mb

Wielkie eksperymenty. Jednak znalazłem array.forEach()w twoim kodzie, ponieważ wiem, że nie istnieje w IE, czy implementujesz sam? Jak mierzysz jego udział w ogólnym opóźnieniu?
Evi Song

Dzięki, mógłbym je powtórzyć, ponieważ minęło trochę czasu od pierwszych testów. Jeśli chodzi o forEach(). Nie, sam tego nie wdrożyłem, użyłem kolby Array.prototype.forEach(). Według Mozilla Developer Network aka MDN z IE9 ma natywne wsparcie.
Jakub Gadkowski

Dzięki. Moja wiedza wymaga odświeżenia. Później użyję Array.prototype.forEach()jak najwięcej, jeśli mój projekt nie obsługuje wczesnych wersji IE.
Evi Song

Kod można by znacznie przyspieszyć (~ 2500 ms w Firefoksie, ~ 700 ms w Chrome): podziel whilepętlę na dwie części, pierwszą jak w stackoverflow.com/a/3027249/1235394, która wypełnia localStorage wykładniczo rosnącymi fragmentami danych, a następnie drugą część małe kawałki o stałej wielkości, aby całkowicie zapełnić magazyn. Strona testowa: jsfiddle.net/pqpps3tk/1
Victor,

IE10 Rocks ... Wciąż najszybsza przeglądarka do pobrania Chrome :)
Ruslan Abuzant

11

Bieżący rozmiar danych lokalnego magazynu można uzyskać za pomocą funkcji Blob. To może nie działać w starszych przeglądarkach, sprawdź obsługę new BlobiObject.values() na caniuse.

Przykład:

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

Object.values ​​() zamienia obiekt localStorage na tablicę. Blob zamienia tablicę w surowe dane.


3
Myślę, że Blobnie ogranicza kodowania ciągów do UTF-16, więc może to być najbardziej niezawodna metoda. new Blob(['X']).size;= 1, podczas gdy new Blob(['☃']).size(U + 2603 / snowman character) ==> 3. Rozwiązania oparte na String.prototype.lengthnie uwzględniają tego (zajmują się „znakami”), podczas gdy limity / limity pamięci prawdopodobnie tak (zajmują się bajtami) i mogę sobie wyobrazić prowadzi to do niespodzianek, na przykład podczas przechowywania znaków innych niż angielskie / ASCII.
iX3

Użyłem odpowiedzi Jeda, która oblicza rozmiar localStorage z długością ciągów, aby przetestować rozwiązanie Blob w Chrome i FF. W pierwszym teście wypełniłem localStorage znakiem „1”. w drugim teście wypełniłem localStorage znakiem „☃”, który ma większy rozmiar w obiekcie Blob. W obu przypadkach uzyskałem dokładnie taką samą maksymalną długość localStorage. Tak więc rozmiar znaków BLOB nie wpływa na ograniczenie localStorage. Dlatego Blob nie powinien być używany do tego celu.
Vincente

6

Możesz obliczyć lokalną pamięć za pomocą następujących metod:

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

Ostatecznie rozmiar w bajtach zostanie zarejestrowany w przeglądarce.


4

Użyłbym kodu @tennisgen, który pobiera wszystko i liczy zawartość, ale liczę same klucze:

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

Sposób, w jaki poradziłem sobie z tym problemem, polega na utworzeniu funkcji do znajdowania używanego miejsca i pozostałego miejsca w pamięci lokalnej, a następnie funkcji, która wywołuje te funkcje, aby określić maksymalną przestrzeń dyskową.

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 to zabójca wydajności, lepiej używaj String.repeat tam, gdzie jest dostępny (to znaczy wszędzie z wyjątkiem IE)
pkExec

2

Oprócz odpowiedzi @ serge, która jest tutaj najczęściej głosowana, należy wziąć pod uwagę rozmiar kluczy. Poniższy kod doda rozmiar kluczy przechowywanych wlocalStorage

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

Odkryłam, że Firefox wraca undefineddo pozycji length, w niektórych przypadkach, więc dodałem warunkowa dodaniem: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin

@camilokawerin, nie powinno, chyba że niezdefiniowana wartość jest zapisana w magazynie, ponieważ String jest jedynym typem obsługiwanym przez localStorage, a String ma właściwość Length. Czy mógłbyś zamieścić jakiś przykład na jsfiddle lub coś podobnego?
Mihir

1

Zgodnie ze specyfikacją każdy znak w ciągu ma 16 bitów.

Ale sprawdzenie za pomocą chrome (Ustawienia> Ustawienia treści> Pliki cookie i dane witryn) pokazuje nam, że zainicjowanie localStorage zajmuje 3kB (rozmiar narzutu)

Rozmiar przechowywanych danych jest zgodny z tą relacją (z dokładnością do 1kB)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

gdzie localStorage.x jest ciągiem przechowywania.


0

// Pamięć jest zajęta przez klucz i wartość, więc zaktualizowany kod.

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

Tak, to pytanie zostało zadane jakieś 10 lat temu. Ale dla tych, którzy są zainteresowani (jak ja, ponieważ buduję edytor tekstu offline, który zapisuje dane w lokalnej pamięci) i ssą programowanie, możesz użyć czegoś prostego:

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

Najlepszym sposobem, aby uzyskać zapełnioną przestrzeń dyskową, jest wyświetlenie ustawień witryny (powiedzmy, jeśli zapisałeś obraz w pamięci lokalnej). Przynajmniej w chrome możesz zobaczyć ilość wykorzystanych bajtów (czyli: 1222 bajty). Jednak najlepsze sposoby na zobaczenie zapełnionej lokalnej pamięci za pomocą js zostały już wspomniane powyżej, więc używaj ich.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.