Cómo encontrar el tamaño de localStorage

117

Actualmente estoy desarrollando un sitio que utilizará localStorage de HTML5. Leí todo sobre las limitaciones de tamaño para diferentes navegadores. Sin embargo, no he visto nada sobre cómo averiguar el tamaño actual de una instancia de localStorage. Esta pregunta parece indicar que JavaScript no tiene una forma integrada de mostrar el tamaño de una variable determinada. ¿LocalStorage tiene una propiedad de tamaño de memoria que no he visto? ¿Hay una forma fácil de hacer esto que me falta?

Mi sitio está diseñado para permitir que los usuarios ingresen información en un modo "sin conexión", por lo que es muy importante poder darles una advertencia cuando el almacenamiento está casi lleno.

derivación
fuente

Respuestas:

220

Ejecute este fragmento en la consola de JavaScript (versión de una línea):

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

El mismo código en varias líneas para leer.

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

o agregue este texto en el campo 'ubicación' de un marcador para un uso conveniente

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

Los fragmentos de PS se actualizan de acuerdo con la solicitud en el comentario. Ahora el cálculo incluye la longitud de la clave en sí. Cada longitud se multiplica por 2 porque el carácter en javascript se almacena como UTF-16 (ocupa 2 bytes)

PPS debería funcionar tanto en Chrome como en Firefox.

Serge Seletskyy
fuente
8
Pegue esto en la consola para ver el total: var t = 0; para (var x en localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Henry
5
@Micah Javascript usa UTF16 internamente, por lo que debido a que cada carácter se almacena como dos bytes, debe multiplicar el número de caracteres por dos para obtener el espacio real utilizado. (Probablemente ya haya descubierto esto, pero pensé que valía la pena señalarlo aquí solo porque cualquier otra persona tiene la misma pregunta)
Rebecka
2
@Serge, esta respuesta es la más votada, por lo tanto, se publica aquí var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir
17
Aquí hay una versión modificada que también representa 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
Hay un error en el marcador. Estás usando variables subrayadas en el código principal y nombres normales en bookmarklet. Un solo subrayado lo _xrompe. Simplemente elimine el subrayado.
Soul Reaver
46

Saliendo de lo que @Shourav dijo anteriormente, escribí una pequeña función que debería tomar con precisión todas sus localStorageclaves (para el dominio actual) y calcular el tamaño combinado para que sepa exactamente cuánta memoria ocupa su localStorageobjeto:

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

El mío regresó: "30.896484375 KB"

tenista
fuente
1
Gracias @tennisgent. El mío funcionó para IE11, FF> 26 y también para Chrome.
Akki922234
18

IE tiene una remainingSpace propiedad del objeto de almacenamiento. Los otros navegadores no tienen equivalente en este momento.

Creo que la cantidad de espacio predeterminada es de 5 MB, aunque no lo he probado personalmente.

Adán
fuente
1
Esta es una propiedad exclusiva de IE
jas-
¿Cuál es el límite de 5 MB por sitio o en general para todos los sitios?
divyenduz
@divyenduz por sitio, creo
Adam
2
Tenga en cuenta que la propiedad localStorage.remainingSpace devuelve el número restante de caracteres UTF-16 permitidos para el objeto de almacenamiento. NO el tamaño restante en bytes. Referencia
Mihir
14

Aquí hay un ejemplo simple de cómo hacer esto y debería funcionar con todos los navegadores.

alert(1024 * 1024 * 5 - unescape(encodeURIComponent(JSON.stringify(localStorage))).length);
jas-
fuente
¿No necesitas un * 8 en alguna parte?
George Mauer
1
Depende del conjunto de caracteres (es decir, utf8, etc.) que eso no tiene en cuenta
jas
¿Da esto el tamaño en bytes o en bits?
JamesTheAwesomeDude
6
Este ejemplo asume incorrectamente que localStorage tiene el mismo límite fijo en 5 MB (5 * 1024 * 1024) en cada navegador.
Victor
Eso es de acuerdo con la especificación presentada por el w3c.
jas-
13

Espero que esto ayude a alguien.

Debido a que Jas- example en jsfiddle no me funciona, se me ocurrió esta solución. (gracias a Serge Seletskyy y Shourav por sus bits que usé en el código a continuación)

A continuación se muestra la función que se puede usar para probar cuánto espacio hay disponible para localStorage y (si ya hay claves en lS) cuánto espacio queda.

Es un poco de fuerza bruta pero funciona en casi todos los navegadores ... excepto en Firefox. Bueno, en el escritorio FF se necesitan siglos (4-5 minutos) en completarse, y en Android simplemente falla.

Debajo de la función hay un breve resumen de las pruebas que he realizado en diferentes navegadores en diferentes plataformas. ¡Disfrutar!

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
}

Y como se prometió anteriormente, algunas pruebas en diferentes navegadores:

GalaxyTab 10.1

  • Almohadilla Maxthon 1.7 ~ 1130ms 5Mb
  • Firefox 20.0 (Beta 20.0) se bloqueó tanto
  • Cromo 25.0.1364.169 ~ 22250ms / 5Mb
  • Nativo (se identifica como Safari 4.0 / Webkit534.30) ~ 995ms / 5Mb

iPhone 4s iOS 6.1.3

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

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

  • Safari 6.0.3 ~ 105ms / 5Mb
  • Cromo 26.0.1410.43 ~ 3400ms / 5Mb
  • Firefox 20.0 300150ms (!) / 10Mb (después de quejarse de que el script se ejecuta demasiado)

iPad 3 iOS 6.1.3

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

Windows 7 -64b (Core 2 Duo 2,93 de memoria de 6 Gb)

  • Safari 5.1.7 ~ 80 ms / 5 Mb
  • Cromo 26.0.1410.43 ~ 1220ms / 5Mb
  • Firefox 20.0 228500ms (!) / 10Mb (después de quejarse de que el script se ejecuta demasiado)
  • IE9 ~ 17900ms /9.54Mb (si hay algún console.logs en el código, no funciona hasta que se abre DevTools)
  • Opera 12.15 ~ 4212ms /3.55Mb (aquí es cuando se selecciona 5Mb, pero Opera pregunta amablemente si queremos aumentar la cantidad de lS, desafortunadamente falla si la prueba se realiza varias veces seguidas)

Gana 8 (bajo Parallels 8)

  • IE10 ~ 7850ms /9.54Mb
Jakub Gadkowski
fuente
Grandes experimentos. Sin embargo, encontré array.forEach()en su código, como sé que no existe en IE, ¿lo implementa usted mismo? ¿Cómo mide su contribución a la latencia general?
Evi Song
Gracias, podría rehacerlos ya que pasó un tiempo desde las pruebas iniciales. En cuanto al forEach(). No, no lo he implementado yo mismo, utilicé el stock Array.prototype.forEach(). Según Mozilla Developer Network, también conocido como MDN de IE9, tiene soporte nativo.
Jakub Gadkowski
Gracias. Mi conocimiento necesita ser actualizado. Más adelante usaré Array.prototype.forEach()tanto como sea posible si mi proyecto no es compatible con las primeras versiones de IE.
Evi Song
El código podría hacerse significativamente más rápido (~ 2500ms en Firefox, ~ 700ms en Chrome): dividir el whilebucle en dos partes, la primera como en stackoverflow.com/a/3027249/1235394 que llena localStorage con fragmentos de datos que crecen exponencialmente, luego la segunda parte con trozos pequeños de tamaño fijo para llenar el almacenamiento por completo. Página de prueba: jsfiddle.net/pqpps3tk/1
Victor
IE10 Rocks .. Aún así, el navegador más rápido para descargar Chrome :)
Ruslan Abuzant
11

Puede obtener el tamaño actual de los datos de almacenamiento local mediante la función Blob. Es posible que esto no funcione en navegadores antiguos, verifique el soporte para new Bloby Object.values()en caniuse.

Ejemplo:

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

Object.values ​​() convierte el objeto localStorage en una matriz. Blob convierte la matriz en datos sin procesar.

P Roitto
fuente
3
Creo Blobque no restringe la codificación de cadenas a UTF-16, por lo que este podría ser el método más confiable. new Blob(['X']).size;= 1 considerando new Blob(['☃']).size(U + 2603 / carácter de muñeco de nieve) ==> 3. Las soluciones basadas en String.prototype.lengthno tienen esto en cuenta (tratan con "caracteres") mientras que las cuotas / límites de almacenamiento probablemente sí (tratan con bytes), y podría imaginar esto lleva a sorpresas, por ejemplo, al almacenar caracteres no ingleses / ASCII.
iX3
Usé la respuesta de Jed, que calcula el tamaño de localStorage con la longitud de las cadenas para probar la solución Blob en Chrome y FF. En la primera prueba, llené localStorage con el signo '1'. en la segunda prueba, llené localStorage con el signo '' ☃ '' que tiene un tamaño más grande en el objeto Blob. En ambos casos obtuve exactamente la misma longitud máxima de almacenamiento local. Por lo tanto, el tamaño de blob de caracteres no afecta la limitación de localStorage. Es por eso que Blob no debe usarse para este propósito.
Vicente
6

Puede calcular su almacenamiento local mediante los siguientes métodos:

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

Finalmente, el tamaño en bytes se registrará en el navegador.

Usman Faisal
fuente
4

Usaría el código de @tennisgen que obtiene todo y cuenta el contenido, pero cuento las claves en sí mismas:

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)';
    };
Arnaud Valensi
fuente
3

La forma en que resolví este problema fue crear funciones para averiguar el espacio utilizado y el espacio restante en el almacenamiento local y luego una función que llama a esas funciones para determinar el espacio máximo de almacenamiento.

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;
}
Jed
fuente
Array.join es un asesino del rendimiento, mejor use String.repeat donde esté disponible (eso significa en todas partes excepto IE)
pkExec
2

Además de la respuesta de @ serge, que es la más votada aquí, se debe considerar el tamaño de las claves. El código a continuación agregará el tamaño de las claves almacenadas enlocalStorage

var t = 0; 
for (var x in localStorage) { 
    t += (x.length + localStorage[x].length) * 2; 
} 
console.log((t / 1024) + " KB");
Mihir
fuente
He encontrado que los rendimientos de Firefox undefinedpara el elemento lengthen algunos casos, por lo que hemos añadido un condicional a la adición: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin
@camilokawerin, no debería hacerlo a menos que se guarde un valor indefinido en el almacenamiento, porque String es el único tipo que es compatible con localStorage y String tiene la propiedad Length. ¿Podrías publicar algún ejemplo en jsfiddle o algo similar?
Mihir
1

Según la especificación, cada carácter de una cadena es de 16 bits.

Pero inspeccionar con Chrome (Configuración> Configuración de contenido> Cookies y datos del sitio) nos muestra que iniciar localStorage toma 3kB (tamaño de sobrecarga)

Y el tamaño de los datos almacenados sigue esta relación (con una precisión de 1 kB)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

donde localStorage.x es su cadena de almacenamiento.

ShouravBR
fuente
0

// La memoria ocupa tanto la clave como el valor, por lo que el código actualizado.

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]);
Dipak Prajapati
fuente
0

Sí, esta pregunta se hizo como hace 10 años. Pero para aquellos interesados ​​(como yo, ya que estoy construyendo un editor de texto sin conexión que guarda datos con almacenamiento local) y apestan a la programación, podrían usar algo simple como esto:

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

La mejor manera de llenar la cantidad de almacenamiento es ver la configuración del sitio (por ejemplo, si almacenó una imagen en el almacenamiento local). Al menos en Chrome, puede ver la cantidad de bytes utilizados (es decir, 1222 bytes). Sin embargo, las mejores formas de ver el almacenamiento local lleno con js ya se han mencionado anteriormente, así que úselas.

Nathan Su
fuente
-2
window.localStorage.remainingSpace
Pradeep Singh
fuente
8
Como se señaló anteriormente, esta es una propiedad solo de IE.
Rafi Jacoby