Calculando o uso do espaço de armazenamento local
-
26-09-2019 - |
Pergunta
Estou criando um aplicativo usando o Editor Bespin e o LocalSorage do HTML5. Ele armazena todos os arquivos localmente e ajuda na gramática, usa o JSLINT e alguns outros analisadores para CSS e HTML para ajudar o usuário.
Quero calcular quanto do limite de armazenamento local foi usado e quanto há realmente. Isso é possível hoje? Eu estava pensando em não simplesmente calcular os bits que são armazenados. Mas, novamente, não tenho certeza do que mais existe que não posso me medir.
Solução 2
Não encontrei uma maneira universal de obter o limite restante dos navegadores que eu precisava, mas descobri que, quando você atinge o limite, há uma mensagem de erro que aparece. Isso é de curso diferente em cada navegador.
Para maximizar, usei este pequeno script:
for (var i = 0, data = "m"; i < 40; i++) {
try {
localStorage.setItem("DATA", data);
data = data + data;
} catch(e) {
var storageSize = Math.round(JSON.stringify(localStorage).length / 1024);
console.log("LIMIT REACHED: (" + i + ") " + storageSize + "K");
console.log(e);
break;
}
}
localStorage.removeItem("DATA");
Daquele eu recebi esta informação:
Google Chrome
- Domexception:
- Código: 22
- Mensagem: "Falha ao executar 'setItem' em 'armazenamento': definir o valor de 'dados' excedeu a cota".
- Nome: "QuotAexcededError"
Mozilla Firefox
- Domexception:
- Código: 1014
- Mensagem: "Tamanho máximo de armazenamento persistente alcançado"
- Nome: "ns_error_dom_quota_reached"
Safári
- Domexception:
- Código: 22
- Mensagem: "QuotaExcededError: DOM Exceção 22"
- Nome: "QuotAexcededError"
Internet Explorer, Edge (comunidade)
- Domexception:
- Código: 22
- Mensagem: "QuotaExcededError"
- Nome: "QuotAexcededError"
Minha solução
Até agora, minha solução é adicionar uma chamada extra cada vez que o usuário salvaria qualquer coisa. E se a exceção for capturada, eu diria a eles que eles estão ficando sem capacidade de armazenamento.
Editar: exclua os dados adicionados
Esqueci de mencionar que, para que isso realmente funcione, você precisaria excluir o DATA
item que foi definido originalmente. A mudança é refletida acima usando o remover item() função.
Outras dicas
Você pode ter uma idéia aproximada usando os métodos JSON para transformar todo o objeto LocalStorage para uma string json:
JSON.stringify(localStorage).length
Não sei como seria preciso, especialmente com os poucos bytes de marcação adicional se você estiver usando objetos adicionais- mas acho que é melhor do que pensar que você está apenas empurrando 28k e, em vez disso, fazendo 280k (ou vice- versa).
IE8 implementa o remainingSpace
propriedade para esse fim:
alert(window.localStorage.remainingSpace); // should return 5000000 when empty
Infelizmente, parece que isso não está disponível nos outros navegadores. No entanto, não tenho certeza se eles implementam algo semelhante.
Você pode usar a linha abaixo para calcular com precisão este valor e Aqui está um jsfiddle Para ilustração de seu uso
alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
Tornou -se hoje durante o teste (excedendo a cota de armazenamento) e criou uma solução. IMO, sabendo qual é o limite e onde estamos em relação é muito menos valioso do que implementar uma maneira funcional de continuar armazenando além da cota.
Assim, em vez de tentar fazer comparações de tamanho e verificações de capacidade, vamos reagir quando atingirmos a cota, reduzir nosso armazenamento atual em um terceiro e retomar o armazenamento. Se a referida redução falhar, pare de armazenar.
set: function( param, val ) {
try{
localStorage.setItem( param, typeof value == 'object' ? JSON.stringify(value) : value )
localStorage.setItem( 'lastStore', new Date().getTime() )
}
catch(e){
if( e.code === 22 ){
// we've hit our local storage limit! lets remove 1/3rd of the entries (hopefully chronologically)
// and try again... If we fail to remove entries, lets silently give up
console.log('Local storage capacity reached.')
var maxLength = localStorage.length
, reduceBy = ~~(maxLength / 3);
for( var i = 0; i < reduceBy; i++ ){
if( localStorage.key(0) ){
localStorage.removeItem( localStorage.key(0) );
}
else break;
}
if( localStorage.length < maxLength ){
console.log('Cache data reduced to fit new entries. (' + maxLength + ' => ' + localStorage.length + ')');
public.set( param, value );
}
else {
console.log('Could not reduce cache size. Removing session cache setting from this instance.');
public.set = function(){}
}
}
}
}
Essa função vive dentro de um objeto de wrapper, então público. O conjunto simplesmente se chama. Agora, podemos adicionar ao armazenamento e não nos preocupar o que é a cota ou o quão perto também estamos. Se uma única loja estiver excedendo 1/3, o tamanho da cota é onde essa função parará de abater e parar de armazenar e, nesse ponto, você não deve estar em cache de qualquer maneira, certo?
Para adicionar aos resultados dos testes do navegador:
Raposa de fogoi = 22.
SafáriA versão 5.0.4 no meu Mac não pendurou. Erro como Chrome. i = 21.
ÓperaDiz ao usuário que o site deseja armazenar dados, mas não tem espaço suficiente. O usuário pode rejeitar a solicitação, aumentar o limite para o valor necessário ou para vários outros limites ou defini -lo como ilimitado. Vá para Opera: WebStorage para dizer se essa mensagem aparece ou não. i = 20. O erro lançado é o mesmo que o Chrome.
IE9 Modo de padrõesErro como Chrome. i = 22.
IE9 no modo de padrões IE8Mensagem do console "Erro: não há armazenamento suficiente para concluir esta operação". i = 22
IE9 em modos mais antigoserro de objeto. i = 22.
Ie8Não tenha uma cópia para testar, mas o armazenamento local é suportado (http://stackoverflow.com/questions/3452816/does-ie8-support-to-of-the-box-in-localstorage)
IE7 e abaixoNão suporta armazenamento local.
Você pode testar seu navegador com isso Teste de suporte de armazenamento na Web
eu testei Raposa de fogo no meu tablet Android e no laptop do Windows e Cromo Apenas nos resultados do Windows:
Raposa de fogo(janelas):
- LocalStorage: 5120k char
- SessionStorage: 5120k char
- LocalStorage: *não suportado
Raposa de fogo(Android):
- LocalStorage: 2560k char
- SessionStorage: Ilimitado (exatamente o teste é executado até 10240k char == 20480K byte)
- LocalStorage: não suportado
Cromo(janelas):
- LocalStorage: 5120k char
- SessionStorage: 5120k char
- LocalStorage: não suportado
Atualizar
No Google Chrome, versão 52.0.2743.116 m (64 bits) limites onde um pouco menor em 5101k
personagens. Isso significa que o máximo disponível pode mudar nas versões.
Gostaria de poder adicionar isso em um comentário - não é suficiente representante, desculpe.
Eu executei alguns testes de perf - esperando que o JSON.Stringify (LocalStorage). Comprimento seja um OP caro em uma grande ocupação de armazenamento local.
http://jsperf.com/occupied-localstorage-json-tringify-mength
É de fato tão - cerca de 50x mais caro do que acompanhar o que você está armazenando e piora o local mais cheio.
Esta função recebe o exato armazenamento disponível / à esquerda:
Fiz uma suíte de funções úteis para o LocalStorage *aqui*
http://jsfiddle.net/kzq6jgqa/3/
function getLeftStorageSize() {
var itemBackup = localStorage.getItem("");
var increase = true;
var data = "1";
var totalData = "";
var trytotalData = "";
while (true) {
try {
trytotalData = totalData + data;
localStorage.setItem("", trytotalData);
totalData = trytotalData;
if (increase) data += data;
} catch (e) {
if (data.length < 2) break;
increase = false;
data = data.substr(data.length / 2);
}
}
localStorage.setItem("", itemBackup);
return totalData.length;
}
// Examples
document.write("calculating..");
var storageLeft = getLeftStorageSize();
console.log(storageLeft);
document.write(storageLeft + "");
// to get the maximum possible *clear* the storage
localStorage.clear();
var storageMax = getLeftStorageSize();
Observe que isso não é muito rápido, então não use isso o tempo todo.
Com isso, também descobri que: o nome do item ocupará tanto espaço quanto seu comprimento, o valor do item também ocupará tanto espaço quanto seu comprimento.
Armazenamento máximo que recebi - tudo cerca de 5m:
- 5000000 CARS - Edge
- 5242880 Chars - Chrome
- 5242880 Chars - Firefox
- 5000000 chars - ou seja
Você encontrará algum código superficiado no violino para ver o progresso no console.
Levei algum tempo para fazer, espero que isso ajude ☺
Eu precisava realmente simular e testar o que meu módulo fará quando o armazenamento estiver cheio, então eu precisava obter uma precisão próxima quando o armazenamento estiver cheio, em vez da resposta aceita, o que perde essa precisão a uma taxa de i^2.
Aqui está o meu script, que sempre deve produzir uma precisão de 10 quando a tampa da memória é alcançada e rapidamente, apesar de ter algumas otimizações fáceis ... editar: melhorei o script e com uma precisão exata:
function fillStorage() {
var originalStr = "1010101010";
var unfold = function(str, times) {
for(var i = 0; i < times; i++)
str += str;
return str;
}
var fold = function(str, times) {
for(var i = 0; i < times; i++) {
var mid = str.length/2;
str = str.substr(0, mid);
}
return str;
}
var runningStr = originalStr;
localStorage.setItem("filler", runningStr);
while(true) {
try {
runningStr = unfold(runningStr, 1);
console.log("unfolded str: ", runningStr.length)
localStorage.setItem("filler", runningStr);
} catch (err) {
break;
}
}
runningStr = fold(runningStr, 1);
var linearFill = function (str1) {
localStorage.setItem("filler", localStorage.getItem("filler") + str1);
}
//keep linear filling until running string is no more...
while(true) {
try {
linearFill(runningStr)
} catch (err) {
runningStr = fold(runningStr, 1);
console.log("folded str: ", runningStr.length)
if(runningStr.length == 0)
break;
}
}
console.log("Final length: ", JSON.stringify(localStorage).length)
}
Isso pode ajudar alguém. No Chrome, é possível pedir ao usuário que permita usar mais espaço em disco, se necessário:
// Request Quota (only for File System API)
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
window.webkitRequestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
}, function(e) {
console.log('Error', e);
});
Visita https://developers.google.com/chrome/whitepapers/storage#asking_more para mais informações.
try {
var count = 100;
var message = "LocalStorageIsNOTFull";
for (var i = 0; i <= count; count + 250) {
message += message;
localStorage.setItem("stringData", message);
console.log(localStorage);
console.log(count);
}
}
catch (e) {
console.log("Local Storage is full, Please empty data");
// fires When localstorage gets full
// you can handle error here ot emply the local storage
}