Como encontrar o tamanho de localStorage

117

Atualmente, estou desenvolvendo um site que fará uso do localStorage do HTML5. Eu li tudo sobre as limitações de tamanho para diferentes navegadores. No entanto, não vi nada sobre como descobrir o tamanho atual de uma instância localStorage. Esta pergunta parece indicar que o JavaScript não tem uma maneira embutida de mostrar o tamanho de uma determinada variável. O localStorage tem uma propriedade de tamanho de memória que eu não vi? Existe uma maneira fácil de fazer isso que estou perdendo?

Meu site foi criado para permitir que os usuários insiram informações no modo 'offline', portanto, poder avisá-los quando o armazenamento estiver quase cheio é muito importante.

derivação
fonte

Respostas:

219

Execute este snippet no console JavaScript (versão de uma linha):

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 mesmo código em várias linhas para fins de leitura

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

ou adicione este texto no campo 'localização' de um favorito para 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")); 

Snippets de PS são atualizados de acordo com a solicitação no comentário. Agora, o cálculo inclui o comprimento da própria chave. Cada comprimento é multiplicado por 2 porque o caractere em javascript armazena como UTF-16 (ocupa 2 bytes)

PPS deve funcionar tanto no Chrome quanto no Firefox.

Serge Seletskyy
fonte
8
Cole no console para ver o total: var t = 0; para (var x em localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Henry,
5
@Micah Javascript usa UTF16 internamente, então como cada caractere é armazenado como dois bytes, você precisa multiplicar o número de caracteres por dois para obter o espaço real usado. (Você provavelmente já descobriu isso, mas achei que vale a pena observar aqui apenas para quem mais tem a mesma dúvida)
Rebecka
2
@Serge, esta resposta é mais votada, portanto, postando aqui var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir
17
Aqui está uma versão modificada que também 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");
leva em
1
Há um bug no bookmarklet. Você está usando variáveis ​​sublinhadas no código principal e nomes normais no bookmarklet. Um único sublinhado _xquebra. Simplesmente remova o sublinhado.
Soul Reaver
46

Partindo do que @Shourav disse acima, escrevi uma pequena função que deve pegar com precisão todas as suas localStoragechaves (para o domínio atual) e calcular o tamanho combinado para que você saiba exatamente quanta memória é ocupada pelo seu 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)';
    };

Meu devolvido: "30.896484375 KB"

tenista
fonte
1
Obrigado @tennisgent. O meu funcionou para o IE11, FF> 26 e para o Chrome também.
Akki922234
18

O IE possui uma propriedade permanentSpace do objeto Storage. Os outros navegadores não têm equivalente neste momento.

Eu acredito que a quantidade de espaço padrão é 5 MB, embora eu não tenha testado pessoalmente.

Adão
fonte
1
Esta é uma propriedade somente do IE
jas-
é o limite de 5 MB por site ou no geral para todos os sites?
divyenduz
@divyenduz por site, eu acho
Adam
2
Observe que a propriedade localStorage.remainingSpace retorna o número restante de caracteres UTF-16 permitidos para o objeto de armazenamento. NÃO o tamanho restante em bytes. Referência
Mihir
14

Aqui está um exemplo simples de como fazer isso e deve funcionar com todos os navegadores

alert(1024 * 1024 * 5 - unescape(encodeURIComponent(JSON.stringify(localStorage))).length);
Jas-
fonte
você não precisa de um * 8 em algum lugar aí?
George Mauer
1
Depende do conjunto de caracteres (ou seja, utf8, etc) que não leva em conta
jas-
Isso fornece o tamanho em bytes ou em bits?
JamesTheAwesomeDude
6
Este exemplo assume incorretamente que localStorage tem o mesmo limite fixo em 5 MB (5 * 1024 * 1024) em cada navegador.
Victor
Isso está de acordo com as especificações apresentadas pelo w3c.
jas-
13

Espero que isso ajude alguém.

Porque Jas- exemplo em jsfiddle não funciona para mim, eu vim com esta solução. (obrigado a Serge Seletskyy e Shourav pelos bits que usei no código abaixo)

Abaixo está a função que pode ser usada para testar quanto espaço está disponível para localStorage e (se alguma chave já estiver em IS) quanto espaço resta.

É um pouco de força bruta, mas funciona em quase todos os navegadores ... exceto no Firefox. Bem, no FF de desktop leva anos (4-5min) para ser concluído, e no Android simplesmente trava.

Abaixo da função está um breve resumo dos testes que fiz em diferentes navegadores em diferentes plataformas. Aproveitar!

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 como prometido acima, alguns testes em diferentes navegadores:

GalaxyTab 10.1

  • Maxthon Pad 1.7 ~ 1130ms 5Mb
  • Firefox 20.0 (Beta 20.0) travou ambos
  • Chrome 25.0.1364.169 ~ 22250ms / 5Mb
  • Nativo (identifica-se como Safari 4.0 / Webkit534.30) ~ 995ms / 5Mb

iPhone 4s iOS 6.1.3

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

MacBook Pro OSX 1.8.3 (Core 2 Duo 2.66 8 Gb de memória)

  • Safari 6.0.3 ~ 105ms / 5Mb
  • Chrome 26.0.1410.43 ~ 3400ms / 5Mb
  • Firefox 20.0 300150ms (!) / 10Mb (depois de reclamar sobre a longa execução do script)

iPad 3 iOS 6.1.3

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

Windows 7 -64b (Core 2 Duo 2,93 6 Gb de memória)

  • Safari 5.1.7 ~ 80ms / 5Mb
  • Chrome 26.0.1410.43 ~ 1220ms / 5Mb
  • Firefox 20.0 228500ms (!) / 10Mb (após reclamar sobre a longa execução do script)
  • IE9 ~ 17900ms /9.54Mb (se algum console.log estiver no código, não funciona até que DevTools seja aberto)
  • Opera 12,15 ~ 4212ms / 3,55Mb (isto é quando 5Mb é selecionado, mas o Opera pergunta educadamente se queremos aumentar a quantidade de lS, infelizmente ele trava se o teste for realizado algumas vezes consecutivas)

Vitória 8 (no Paralelo 8)

  • IE10 ~ 7850ms /9,54Mb
Jakub Gadkowski
fonte
Ótimos experimentos. Porém eu encontrei array.forEach()no seu código, como sei que não existe no IE, você implementa sozinho? Como você mede sua contribuição para a latência geral?
Evi Song
Obrigado, devo refazê-los já que passou algum tempo desde os testes iniciais. Quanto ao forEach(). Não, eu não implementei, usei o estoque Array.prototype.forEach(). De acordo com o Mozilla Developer Network, também conhecido como MDN do IE9, ele tem suporte nativo.
Jakub Gadkowski
Obrigado. Meu conhecimento precisa ser atualizado. Posteriormente, usarei o Array.prototype.forEach()máximo possível se meu projeto não for compatível com as versões anteriores do IE.
Evi Song
O código pode ser feito significativamente mais rápido (~ 2500ms no Firefox, ~ 700ms no Chrome): whileloop dividido em duas partes, a primeira como stackoverflow.com/a/3027249/1235394 que preenche localStorage com blocos de dados que crescem exponencialmente, depois a segunda parte com pequenos pedaços de tamanho fixo para preencher completamente o armazenamento. Página de teste: jsfiddle.net/pqpps3tk/1
Victor
IE10 Rocks .. Ainda assim, o navegador mais rápido para baixar o Chrome :)
Ruslan Abuzant
11

Você pode obter o tamanho atual dos dados de armazenamento local usando a função Blob. Isso pode não funcionar em navegadores antigos, verifique o suporte para new Blobe Object.values()em caniuse.

Exemplo:

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

Object.values ​​() transforma o objeto localStorage em um array. Blob transforma o array em dados brutos.

P Roitto
fonte
3
Acho Blobque não restringe a codificação de string a UTF-16, então esse pode ser o método mais confiável. new Blob(['X']).size;= 1 enquanto new Blob(['☃']).size(U + 2603 / caractere do boneco de neve) ==> 3. Soluções baseadas em String.prototype.lengthnão levam isso em consideração (lidam com "caracteres") enquanto cotas / limites de armazenamento provavelmente o fazem (lidam com bytes), e eu poderia imaginar isso leva a surpresas, por exemplo, ao armazenar caracteres não ingleses / ASCII.
iX3
Usei a resposta de Jed, que calcula o tamanho localStorage com o comprimento das strings para testar a solução Blob no Chrome & FF. No primeiro teste, preenchi localStorage com o sinal '1'. no segundo teste, preenchi localStorage com o sinal '' ☃ '' que tem tamanho maior no objeto Blob. Em ambos os casos, obtive exatamente o mesmo comprimento máximo localStorage. Portanto, o tamanho do Blob dos caracteres não afeta a limitação de localStorage. É por isso que Blob não deve ser usado para essa finalidade.
Vincente
6

Você pode calcular seu armazenamento local pelos seguintes 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, o tamanho em bytes será registrado no navegador.

Usman Faisal
fonte
4

Eu usaria o código de @tennisgen que pega tudo e conta o conteúdo, mas eu conto as chaves:

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
fonte
3

A maneira como resolvi esse problema é criar funções para descobrir o espaço usado e o espaço restante no armazenamento local e, em seguida, uma função que chama essas funções para determinar o espaço máximo de armazenamento.

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
fonte
Array.join é um assassino de desempenho, é melhor usar String.repeat onde disponível (isso significa em todos os lugares, exceto no IE)
pkExec 01 de
2

Além da resposta de @ serge, que é mais votada aqui, o tamanho das chaves precisa ser considerado. O código abaixo adicionará o tamanho das chaves armazenadas emlocalStorage

var t = 0; 
for (var x in localStorage) { 
    t += (x.length + localStorage[x].length) * 2; 
} 
console.log((t / 1024) + " KB");
Mihir
fonte
Descobri que Firefox retorna undefinedpara o item length, em alguns casos, por isso eu adicionei uma condicional à adição: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin
@camilokawerin, não deveria, a menos que um valor indefinido seja salvo no armazenamento, porque String é o único tipo compatível com localStorage e String tem a propriedade Length. Você poderia postar algum exemplo no jsfiddle ou algo semelhante?
Mihir
1

Conforme as especificações vão, cada caractere de uma string tem 16 bits.

Mas a inspeção com o Chrome (Configurações> Configurações de conteúdo> Cookies e dados do site) nos mostra que iniciar o localStorage leva 3 kB (tamanho de overhead)

E o tamanho dos dados armazenados segue esta relação (com precisão de 1kB)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

onde localStorage.x é sua string de armazenamento.

ShouravBR
fonte
0

// Memória ocupada por chave e valor, portanto, Código Atualizado.

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
fonte
0

Sim, essa pergunta foi feita há 10 anos. Mas para aqueles interessados ​​(como eu, já que estou construindo um editor de texto offline que salva dados com armazenamento local) e são péssimos em programação, você poderia usar algo simples como isto:

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

A melhor maneira de preencher a quantidade de armazenamento é visualizar as configurações do site (por exemplo, se você armazenou uma imagem no armazenamento local). Pelo menos no cromo, você pode ver a quantidade de bytes usados ​​(ou seja: 1222 bytes). No entanto, as melhores maneiras de ver o armazenamento local preenchido com js já foram mencionadas acima, portanto, use-as.

Nathan Su
fonte
-2
window.localStorage.remainingSpace
Pradeep Singh
fonte
8
Conforme observado acima - esta é uma propriedade somente do IE.
Rafi Jacoby