Come trovare la dimensione di localStorage


117

Attualmente sto sviluppando un sito che utilizzerà localStorage di HTML5. Ho letto tutto sui limiti di dimensione per diversi browser. Tuttavia, non ho visto nulla su come scoprire la dimensione corrente di un'istanza localStorage. Questa domanda sembra indicare che JavaScript non ha un modo integrato per mostrare la dimensione per una data variabile. LocalStorage ha una proprietà della dimensione della memoria che non ho visto? C'è un modo semplice per farlo che mi manca?

Il mio sito ha lo scopo di consentire agli utenti di inserire le informazioni in modalità "offline", quindi essere in grado di avvisarli quando lo spazio di archiviazione è quasi pieno è molto importante.


Risposte:


219

Esegui questo snippet nella console JavaScript (versione a una riga):

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

Lo stesso codice in più righe per leggere bene

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

oppure aggiungi questo testo nel campo "posizione" di un segnalibro per un comodo utilizzo

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

Gli snippet di PS vengono aggiornati in base alla richiesta nel commento. Ora il calcolo include la lunghezza della chiave stessa. Ogni lunghezza viene moltiplicata per 2 perché il carattere in javascript memorizza come UTF-16 (occupa 2 byte)

PPS dovrebbe funzionare sia in Chrome che in Firefox.


8
Incollalo nella console per vedere il totale: var t = 0; for (var x in localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Henry

5
@Micah Javascript utilizza UTF16 internamente, quindi poiché ogni carattere viene memorizzato come due byte, è necessario moltiplicare il numero di caratteri per due per ottenere lo spazio effettivamente utilizzato. (Probabilmente l'hai già scoperto, ma ho pensato che valesse la pena notare qui solo per chiunque altro abbia la stessa domanda)
Rebecka

2
@Serge, questa risposta è più votata, quindi postando qui var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir

17
Ecco una versione modificata che tiene conto anche di 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
C'è un bug nel bookmarklet. Stai usando variabili sottolineate nel codice principale e nomi normali nel bookmarklet. Singolo sottolineato lo _xrompe. Rimuovi semplicemente il trattino basso.
Soul Reaver

46

Partendo da ciò che ha detto @Shourav sopra, ho scritto una piccola funzione che dovrebbe afferrare accuratamente tutte le tue localStoragechiavi (per il dominio corrente) e calcolare la dimensione combinata in modo da sapere esattamente quanta memoria è occupata dal tuo localStorageoggetto:

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

Il mio è tornato: "30.896484375 KB"


1
Grazie @tennisgent. Il mio ha funzionato per IE11, FF> 26 e anche per Chrome.
Akki922234

18

IE ha una remainingSpace proprietà dell'oggetto bagagli. Gli altri browser non hanno equivalenti in questo momento.

Credo che la quantità di spazio predefinita sia 5 MB, anche se non l'ho testata personalmente.


1
Questa è una proprietà esclusiva di IE
jas-

è il limite di 5 MB per sito o complessivamente per tutti i siti?
divyenduz

@divyenduz per sito, credo
Adam

2
Notare che la proprietà localStorage.remainingSpace restituisce il numero rimanente di caratteri UTF-16 consentiti per l'oggetto di archiviazione. NON la dimensione rimanente in byte. Riferimento
Mihir

14

Ecco un semplice esempio di come farlo e dovrebbe funzionare con tutti i browser

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

non hai bisogno di un * 8 da qualche parte lì dentro?
George Mauer

1
Dipende dal set di caratteri (es. Utf8, ecc.) Che non tiene conto
jas-

Questo fornisce la dimensione in byte o in bit?
JamesTheAwesomeDude

6
Questo esempio presume erroneamente che localStorage abbia lo stesso limite fisso in 5 MB (5 * 1024 * 1024) in ogni browser.
Victor

Questo è secondo le specifiche fornite dal w3c.
jas-

13

Spero che questo aiuti qualcuno.

Poiché Jas- esempio su jsfiddle non funziona per me, ho trovato questa soluzione. (grazie a Serge Seletskyy e Shourav per i loro bit che ho usato nel codice qui sotto)

Di seguito è riportata la funzione che può essere utilizzata per verificare quanto spazio è disponibile per localStorage e (se qualche chiave è già in lS) quanto spazio è rimasto.

È un po 'di forza bruta ma funziona in quasi tutti i browser ... a parte Firefox. Ebbene, nel desktop FF ci vogliono anni (4-5 minuti) per completare, e su Android si blocca.

Sotto la funzione c'è un breve riassunto dei test che ho fatto in diversi browser su diverse piattaforme. Godere!

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
}

E come promesso sopra alcuni test in diversi browser:

GalaxyTab 10.1

  • Maxthon Pad 1.7 ~ 1130ms 5Mb
  • Firefox 20.0 (Beta 20.0) si è bloccato entrambi
  • Chrome 25.0.1364.169 ~ 22250ms / 5Mb
  • Nativo (identificato come Safari 4.0 / Webkit534.30) ~ 995ms / 5Mb

iPhone 4s iOS 6.1.3

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

MacBook Pro OSX 1.8.3 (Core 2 Duo 2.66 8 Gb di memoria)

  • Safari 6.0.3 ~ 105 ms / 5 Mb
  • Chrome 26.0.1410.43 ~ 3400ms / 5Mb
  • Firefox 20.0 300150ms (!) / 10Mb (dopo essersi lamentati di uno script troppo lungo)

iPad 3 iOS 6.1.3

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

Windows 7-64b (Core 2 Duo 2.93 6 Gb di memoria)

  • Safari 5.1.7 ~ 80 ms / 5 Mb
  • Chrome 26.0.1410.43 ~ 1220 ms / 5 Mb
  • Firefox 20.0 228500ms (!) / 10Mb (dopo essersi lamentati del fatto che lo script fosse troppo lungo)
  • IE9 ~ 17900ms /9.54Mb (se nel codice sono presenti console.log non funziona fino all'apertura di DevTools)
  • Opera 12.15 ~ 4212ms /3.55Mb (questo è quando 5Mb è selezionato, ma Opera chiede gentilmente se vogliamo aumentare la quantità di lS, sfortunatamente si blocca se il test viene eseguito più volte di seguito)

Vinci 8 (sotto Parallels 8)

  • IE10 ~ 7850 ms / 9,54 Mb

Grandi esperimenti. Comunque ho trovato array.forEach()nel tuo codice, poiché so che non esiste in IE, lo implementi da solo? Come misuri il suo contributo alla latenza complessiva?
Evi Song

Grazie, potrei rifarli visto che è passato del tempo dai test iniziali. Per quanto riguarda il forEach(). No non l'ho implementato da solo, ho usato lo stock Array.prototype.forEach(). Secondo Mozilla Developer Network aka MDN di IE9, ha il supporto nativo.
Jakub Gadkowski,

Grazie. La mia conoscenza deve essere aggiornata. Successivamente userò Array.prototype.forEach()il più possibile se il mio progetto non supporta le prime versioni di IE.
Evi Song

Codice potrebbe essere fatto molto più veloce (~ 2500ms in Firefox, ~ 700ms in Chrome): diviso whileanello in due parti, prima come in stackoverflow.com/a/3027249/1235394 che riempie localStorage con crescita esponenziale blocchi di dati, poi seconda parte con piccoli pezzi di dimensione fissa per riempire completamente lo spazio di archiviazione. Pagina di test: jsfiddle.net/pqpps3tk/1
Victor

IE10 Rocks .. Eppure, il browser più veloce per scaricare Chrome :)
Ruslan Abuzant

11

È possibile ottenere la dimensione corrente dei dati di archiviazione locale utilizzando la funzione BLOB. Questo potrebbe non funzionare nei vecchi browser, controlla il supporto per new Blobe Object.values()su caniuse.

Esempio:

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

Object.values ​​() trasforma l'oggetto localStorage in un array. Blob trasforma la matrice in dati grezzi.


3
Penso Blobche non limiti la codifica delle stringhe a UTF-16, quindi questo potrebbe effettivamente essere il metodo più affidabile. new Blob(['X']).size;= 1 mentre new Blob(['☃']).size(U + 2603 / carattere pupazzo di neve) ==> 3. Le soluzioni basate su String.prototype.lengthnon ne tengono conto (si occupano di "caratteri") mentre le quote / limiti di archiviazione probabilmente sì (si occupano di byte), e potrei immaginare questo porta a sorprese, ad esempio, quando si memorizzano caratteri non inglesi / ASCII.
iX3

Ho usato la risposta di Jed che calcola la dimensione localStorage con la lunghezza delle stringhe per testare la soluzione Blob in Chrome e FF. Nel primo test, ho riempito localStorage con il segno "1". nel secondo test, ho riempito localStorage con il segno '' ☃ '' che ha dimensioni maggiori nell'oggetto Blob. In entrambi i casi ho ottenuto esattamente la stessa lunghezza massima di localStorage. Quindi la dimensione dei caratteri Blob non influisce sulla limitazione di localStorage. Ecco perché Blob non dovrebbe essere usato per questo scopo.
Vincente

6

Puoi calcolare il tuo archivio locale utilizzando i seguenti metodi:

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

Infine la dimensione in byte verrà registrata nel browser.


4

Userei il codice di @tennisgen che ottiene tutto e conta il contenuto, ma conto le chiavi stesse:

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

Il modo in cui ho risolto questo problema è creare funzioni per scoprire lo spazio utilizzato e lo spazio rimanente nell'archiviazione locale e quindi una funzione che chiama tali funzioni per determinare lo spazio di archiviazione massimo.

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 è un killer delle prestazioni, è meglio usare String.repeat dove disponibile (ciò significa ovunque tranne IE)
pkExec

2

Oltre alla risposta di @ serge che è la più votata qui, è necessario considerare la dimensione delle chiavi. Il codice seguente aggiungerà la dimensione delle chiavi memorizzate inlocalStorage

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

Ho scoperto che i rendimenti di Firefox undefinedper la voce lengthin alcuni casi, quindi ho aggiunto un condizionale per l'aggiunta: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin

@camilokawerin, non dovrebbe a meno che non venga salvato un valore indefinito nella memoria, perché String è l'unico tipo supportato con localStorage e String ha la proprietà Length. Potresti postare qualche esempio su jsfiddle o qualcosa di simile?
Mihir

1

Secondo le specifiche, ogni carattere di una stringa è a 16 bit.

Ma l'ispezione con chrome (Impostazioni> Impostazioni contenuti> Cookie e dati del sito) ci mostra che l'avvio di localStorage richiede 3kB (dimensioni generali)

E la dimensione dei dati memorizzati segue questa relazione (precisa a 1kB)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

dove localStorage.x è la stringa di archiviazione.


0

// La memoria occupa sia la chiave che il valore, quindi il codice aggiornato.

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

Sì, questa domanda è stata posta 10 anni fa. Ma per chi è interessato (come me, dato che sto costruendo un editor di testo offline che salva i dati con l'archiviazione locale) e fa schifo alla programmazione, potresti usare qualcosa di semplice come questo:

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

Il modo migliore per riempire la quantità di spazio di archiviazione è visualizzare le impostazioni del sito (ad esempio, se hai archiviato un'immagine nella memoria locale). Almeno in Chrome, puoi vedere la quantità di byte utilizzati (ad esempio: 1222 byte). Tuttavia, i modi migliori per vedere l'archiviazione locale piena con js sono già stati menzionati sopra, quindi usali.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.