Berechnung der Nutzung des localStorage-Speicherplatzes


79

Ich erstelle eine App mit dem Bespin-Editor und dem localStorage von HTML5. Es speichert alle Dateien lokal und hilft bei der Grammatik, verwendet JSLint und einige andere Parser für CSS und HTML, um den Benutzer zu unterstützen.

Ich möchte berechnen, wie viel von der localStorage-Grenze verwendet wurde und wie viel tatsächlich vorhanden ist. Ist das heute möglich? Ich dachte daran, die gespeicherten Bits nicht einfach zu berechnen. Andererseits bin ich mir nicht sicher, was es noch gibt, das ich selbst nicht messen kann.



JavaScript / HTML5 localStorage nützliche Funktionen: stackoverflow.com/q/34245593/4339170
CoderPi

Antworten:


72

Möglicherweise können Sie mithilfe der JSON-Methoden eine ungefähre Vorstellung davon erhalten, wie das gesamte localStorage-Objekt in eine JSON-Zeichenfolge umgewandelt wird:

JSON.stringify(localStorage).length

Ich weiß nicht, wie bytegenau es wäre, insbesondere mit den wenigen Bytes zusätzlichen Markups, wenn Sie zusätzliche Objekte verwenden - aber ich denke, es ist besser, als zu denken, dass Sie nur 28 KB drücken und stattdessen 280 KB ausführen (oder umgekehrt). umgekehrt).


4
Dies ist tatsächlich genau genug, um damit zu arbeiten. Wenn localStorage in Chrome 14 maximal ist, ist JSON.stringify (localStorage) .length === 2636625 oder 2.51448 MB, was nahe genug ist ( dev-test.nemikor.com/web-storage/support-test ). Wird zusammen mit try {} catch {} verwendet und Sie haben genug, um eine Hilfsklasse zu erstellen.
Christopher

13
Beachten Sie, dass dies, wie in dem von Ihnen verknüpften Test ausgeführt, eine Größe in Zeichen und nicht in Bytes ist: "Zeichenfolgen in JavaScript sind UTF-16, sodass jedes Zeichen zwei Bytes Speicher benötigt. Dies bedeutet, dass viele Browser eine 5 haben MB-Limit, Sie können nur 2,5 Millionen Zeichen speichern. "
Mortimer

51

Ich habe keinen universellen Weg gefunden, um das verbleibende Limit für die von mir benötigten Browser zu ermitteln, aber ich habe herausgefunden, dass beim Erreichen des Limits eine Fehlermeldung angezeigt wird. Dies ist natürlich in jedem Browser anders.

Um das Maximum herauszuholen, habe ich dieses kleine Skript verwendet:

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

Daraus habe ich folgende Informationen erhalten:

Google Chrome

  • DOME-Ausnahme:
    • Code: 22
    • message: "Fehler beim Ausführen von 'setItem' in 'Storage': Das Festlegen des Werts von 'data' hat das Kontingent überschritten."
    • Name: "QuotaExceededError"

Mozilla Firefox

  • DOME-Ausnahme:
    • Code: 1014
    • Nachricht: "Maximale Größe des persistenten Speichers erreicht"
    • Name: "NS_ERROR_DOM_QUOTA_REACHED"

Safari

  • DOME-Ausnahme:
    • Code: 22
    • Nachricht: "QuotaExceededError: DOM-Ausnahme 22"
    • Name: "QuotaExceededError"

Internet Explorer, Edge (Community)

  • DOME-Ausnahme:
    • Code: 22
    • Nachricht: "QuotaExceededError"
    • Name: "QuotaExceededError"

Meine Lösung

Bisher besteht meine Lösung darin, jedes Mal, wenn der Benutzer etwas speichert, einen zusätzlichen Anruf hinzuzufügen. Und wenn die Ausnahme abgefangen wird, würde ich ihnen sagen, dass ihnen die Speicherkapazität ausgeht.


Bearbeiten: Löschen Sie die hinzugefügten Daten

Ich habe vergessen zu erwähnen, dass Sie das DATAursprünglich festgelegte Element löschen müssen, damit dies tatsächlich funktioniert . Die Änderung wird oben mithilfe der Funktion removeItem () wiedergegeben .


Sehr schön, wie hoch war der Wert, ials dies jeweils erreicht wurde?
Artlung

20-21 denke ich. Sie können den Test selbst ausführen, wenn Sie möchten.
JeroenEijkhof

IE: ABORT_ERR: 20 Code: 22 Nachricht: "QuotaExceededError" Name: "QuotaExceededError"
Rui Lima

Im IE löst Ihr Code eine Ausnahme vor dem Ende des Leerzeichens aus: window.localStorage.remainingSpace: 805692 | window.localStorage.getItem ("DATA"). Länge: 4194304 | JSON.stringify (localStorage) .length: 4194315 | i: 22
Rui Lima

Gut, dann kann ich den lokalen Speichercode in den try catch-Block einbinden und den Benutzer im catch-Block benachrichtigen, wenn die Größe überschritten wird.
Nirus

26

IE8 implementiert die remainingSpaceEigenschaft zu diesem Zweck:

alert(window.localStorage.remainingSpace);  // should return 5000000 when empty

Leider scheint dies in den anderen Browsern nicht verfügbar zu sein. Ich bin mir jedoch nicht sicher, ob sie etwas Ähnliches implementieren.


1
@WmasterJ: Ich sehe, dass das IE-Team tatsächlich vorgeschlagen hat, dies (oder etwas Ähnliches) in den Standard aufzunehmen (bereits 2008): markmail.org/thread/ugzdcamtyftcyk6y .
Daniel Vassallo

45
Diesmal hatte IE recht. Es scheint offensichtlich, dass dies erforderlich ist.
JeroenEijkhof

Ich verstehe das nicht, sagt Microsoft: "Das localStorage-Attribut bietet dauerhafte Speicherbereiche für Domänen. Es ermöglicht Webanwendungen, aus Leistungsgründen fast 10 MB Benutzerdaten, z. B. ganze Dokumente oder das Postfach eines Benutzers, auf dem Client zu speichern. "" aber am Ende gibt restlicher Raum 5000000 zurück (?!?!) warum?!
Rui Lima

3
@RuiLima, beachten Sie, dass 5000000 Zeichen tatsächlich 10 MB Speicherplatz beanspruchen, da Zeichen in Javascript zwei Bytes anstelle von einem verbrauchen. Anscheinend meldet der IE möglicherweise verbleibende Zeichen anstelle von Bytes oder sie haben ihre Meinung über das Speicherlimit geändert.
Ishmael Smyrnow

1
Diese verbleibende Space-Eigenschaft ist wichtig, wenn Sie erwarten, dass Ihr Überlauf von localStorage eine Ausnahme auslöst: Der IE löst keine aus. Daher müssen Sie diese Eigenschaft vor und nach dem Versuch, in localStorage zu speichern, überprüfen. Wenn sich die Größe nicht geändert hat, wissen Sie, dass Sie Ihr Limit überschritten haben.
Andy

15

Sie können die folgende Zeile verwenden, um diesen Wert genau zu berechnen. Hier ist eine jsfiddle zur Veranschaulichung seiner Verwendung

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

Ich verwende diesen Algorithmus, um den verwendeten Speicherplatz für eine Chrome-Erweiterung zu bestimmen, aber ich erinnere mich, dass ich eine andere SO-Frage gelesen habe (vergessen Sie jetzt, welche), dass JS UTF-16-Zeichenfolgen anstelle von UTF-8 verwendet, und als solche müssen Sie verdoppeln Die Anzahl der Bytes, die Sie mit string.length erhalten. Weißt du, ob das stimmt? Wenn ja, muss ich meinen Code aktualisieren ...
Adam Tuttle

1
Ihre jsfiddle wird nicht in meinen Browser geladen (Mac / Chrome).
Justin

Es sieht so aus, als hätten Sie JSFiddle kaputt gemacht, obwohl Sie die Ausgabe hier immer noch sehen können !
c24w

Müssen Sie nicht mit 8 für 8 Bytes pro Zeichen oder so etwas multiplizieren?
George Mauer

George, in diesem Beispiel wird ein UTF-8-Zeichensatz angenommen, der durch das Meta-Tag "Content-Type" auf den meisten US-amerikanischen HTML-Sites definiert ist. Wenn Sie die Unicode-Unterstützung berücksichtigen möchten, klicken Sie hier auf mathiasbynens.be/notes/javascript-unicode. Für die schnelle Lösung finden Sie hier eine Funktion zur Berücksichtigung der Unicode-Unterstützung in JS github.com/craniumslows/Countable/commit/…
jas -

9

Ich bin heute beim Testen darauf gestoßen (Überschreitung der Speicherquote) und habe eine Lösung gefunden. IMO, zu wissen, was das Limit ist und wo wir in Beziehung stehen, ist weitaus weniger wertvoll als die Implementierung einer funktionalen Methode, um die Speicherung über das Kontingent hinaus fortzusetzen.

Anstatt also zu versuchen, Größenvergleiche und Kapazitätsprüfungen durchzuführen, können wir reagieren, wenn wir das Kontingent erreicht haben, unseren aktuellen Speicher um ein Drittel reduzieren und die Speicherung fortsetzen. Wenn die Reduzierung fehlschlägt, beenden Sie die Speicherung.

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(){}
        }
      }
    }
}

Diese Funktion befindet sich in einem Wrapper-Objekt, daher ruft sich public.set einfach selbst auf. Jetzt können wir den Speicher erweitern und müssen uns keine Sorgen mehr machen, wie hoch das Kontingent ist oder wie nahe wir ihm auch sind. Wenn ein einzelnes Geschäft 1/3 überschreitet, wird diese Funktion bei der Kontingentgröße beendet, und das Speichern wird beendet. An diesem Punkt sollten Sie sowieso nicht zwischenspeichern, oder?


5

So fügen Sie dem Browser Testergebnisse hinzu:

Firefox i = 22.

Safari Version 5.0.4 auf meinem Mac hing nicht. Fehler als Chrome. i = 21.

Opera teilt dem Benutzer mit, dass die Website Daten speichern möchte, aber nicht über genügend Speicherplatz verfügt. Der Benutzer kann die Anfrage ablehnen, das Limit auf den erforderlichen Betrag oder auf mehrere andere Limits erhöhen oder auf unbegrenzt setzen. Gehen Sie zu Opera: Webstorage, um zu sagen, ob diese Meldung angezeigt wird oder nicht. i = 20. Der ausgelöste Fehler ist der gleiche wie bei Chrome.

IE9-Standardmodus Fehler als Chrome. i = 22.

IE9 im IE8-Standardmodus Konsolenmeldung "Fehler: Es ist nicht genügend Speicher verfügbar, um diesen Vorgang abzuschließen". i = 22

IE9 in älteren Modi Objektfehler. i = 22.

IE8 Sie müssen keine Kopie testen, aber der lokale Speicher wird unterstützt (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage).

IE7 und niedriger Unterstützt keinen lokalen Speicher.


3

Sie können Ihren Browser mit diesem Test zur Unterstützung des Webspeichers testen

Ich habe Firefox sowohl auf meinem Android-Tablet als auch auf meinem Windows-Laptop und Chromium nur auf Windows-Ergebnissen getestet :

  1. Firefox (Windows):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : * wird nicht unterstützt
  2. Firefox (Android):

    • localStorage : 2560k char
    • sessionStorage : Unbegrenzt (genau der Test läuft bis zu 10240k char == 20480k byte)
    • localStorage : wird nicht unterstützt
  3. Chrom (Fenster):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : wird nicht unterstützt

Aktualisieren

In Google Chrome Version 52.0.2743.116 m (64-Bit) sind die 5101kZeichen etwas niedriger . Dies bedeutet, dass sich die maximal verfügbaren Versionen ändern können.


Sie meinten angeblich 5120 k char
Juribiyan

@ Juribiyan Ja, das tue ich.
Morteza Tourani

2

Ich wünschte, ich könnte dies in einem Kommentar hinzufügen - nicht genug Wiederholung, sorry.

Ich habe einige Perf-Tests durchgeführt und erwartet, dass JSON.stringify (localStorage) .length bei großer localStorage-Belegung eine teure Operation ist.

http://jsperf.com/occupied-localstorage-json-stringify-length

Es ist in der Tat so - ungefähr 50x teurer als das Verfolgen dessen, was Sie speichern, und es wird schlimmer, je voller localStorage wird.


2

Diese Funktion erhält den genauen verfügbaren Speicherplatz / Links:

Ich habe eine Reihe nützlicher Funktionen für localStorage erstellt * hier *

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

Beachten Sie, dass dies nicht sehr schnell geht. Verwenden Sie es daher nicht immer.

Damit habe ich auch herausgefunden, dass: der Item-Name so viel Platz einnimmt wie seine Länge, der Item-Value auch so viel Platz einnimmt wie ihre Länge.

Maximaler Speicherplatz - alles über 5 Millionen:

  • 5000000 Zeichen - Rand
  • 5242880 Zeichen - Chrome
  • 5242880 Zeichen - Firefox
  • 5000000 Zeichen - IE

In der Geige finden Sie einen auskommentierten Code, um den Fortschritt in der Konsole anzuzeigen.

Ich habe einige Zeit gebraucht, hoffe, das hilft ☺


2
 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
 }

1

Ich musste tatsächlich simulieren und testen, was mein Modul tun wird, wenn der Speicher voll ist, also musste ich genau wissen, wann der Speicher voll ist, und nicht die akzeptierte Antwort, die diese Genauigkeit mit einer Rate von i ^ 2 verliert.

Hier ist mein Skript, das bei Erreichen der Speicherobergrenze immer eine Genauigkeit von 10 erzeugen sollte, und zwar trotz einiger einfacher Optimierungen ziemlich schnell ... BEARBEITEN: Ich habe das Skript besser und mit einer genauen Genauigkeit gemacht:

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

0

Das könnte jemandem helfen. In Chrome kann der Benutzer aufgefordert werden, bei Bedarf mehr Speicherplatz zu verwenden:

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

Besuchen Sie https://developers.google.com/chrome/whitepapers/storage#asking_more für weitere Informationen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.