Jaki jest maksymalny rozmiar wartości localStorage?

542

Ponieważ localStorage(obecnie) obsługuje tylko łańcuchy jako wartości, a aby to zrobić, obiekty muszą zostać poddane strunizacji (przechowywane jako łańcuch JSON) przed ich zapisaniem, czy istnieje określone ograniczenie dotyczące długości wartości.

Czy ktoś wie, czy istnieje definicja, która dotyczy wszystkich przeglądarek?

Codekie
źródło
15
Myślę, że nikt tak naprawdę nie odpowiedział na pytanie „maksymalna długość na wartość”.
Pete Alvin,
@PeteAlvin Właśnie odpowiedziałem na pytanie .
user2428118,
3
Wszystkie przeglądarki: html5rocks.com/en/tutorials/offline/quota-research
MCCCS
@PeteAlvin Ktoś odpowiedział na to w 2015 r. Inne odpowiedzi dotyczą limitu całkowitego rozmiaru, ale nie limitu rozmiaru według wartości .
Ali

Odpowiedzi:

421

Cytując z artykułu z Wikipedii na temat przechowywania w Internecie :

Przechowywanie w Internecie można uprościć jako ulepszenie plików cookie, zapewniając znacznie większą pojemność ( 10 MB na miejsce pochodzenia w Google Chrome ( https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh ), Mozilla Firefox i Opera; 10 MB na obszar pamięci w Internet Explorerze ) oraz lepsze interfejsy programistyczne.

A także cytowanie z artykułu Johna Resiga [opublikowanego w styczniu 2007 r.]:

Przestrzeń magazynowa

Sugeruje się, że dzięki DOM Storage masz znacznie więcej miejsca do przechowywania niż typowe ograniczenia agenta użytkownika nałożone na pliki cookie. Jednak podana kwota nie jest zdefiniowana w specyfikacji, ani nie jest w znaczący sposób rozgłaszana przez klienta użytkownika.

Jeśli spojrzysz na kod źródłowy Mozilli, zobaczymy, że 5120 KB to domyślny rozmiar pamięci dla całej domeny. Daje to znacznie więcej miejsca do pracy niż typowy plik cookie 2 KB.

Jednak rozmiar tego obszaru pamięci może być dostosowywany przez użytkownika (więc obszar pamięci 5 MB nie jest gwarantowany ani nie jest implikowany) i agent użytkownika (na przykład Opera może zapewnić tylko 3 MB - ale tylko czas pokaże. )

Daniel Vassallo
źródło
28
@Cupidvogel nie, oznacza to, że każdy domain( origin) może przechowywać 5 MB na każdym indywidualnym kliencie. Dane są przechowywane na komputerze klienta - w żaden sposób localStoragemechanizm nie wchodzi w interakcje między klientami.
DanielB
6
Nie, chciałem tylko upewnić się, że te same dane są dostępne na wielu stronach dla tej samej domeny. Często znajduję frazy domena i strona, które są pisane synonimicznie, więc po prostu chciałem wiedzieć na pewno!
SexyBeast
9
Czy istnieje jednak ograniczenie jednej wartości? (Jeśli mam dużo flag do przechowywania, jak bezpieczne jest przechowywanie ich jako JSON w jednej nieruchomości?)
phtrivier
5
Mam Safari przy 5 MB i Chrome 39 przy 10 MB (nie jestem pewien, kiedy został zwiększony z 5 MB) Zobacz ten artykuł html5rocks.com/en/tutorials/offline/quota-research
Ally
18
@Cupidvogel: Nie, nie jest to dziedzina, tylko pochodzenie , ponieważ termin ten jest używany w stosunku do Polityki tego samego pochodzenia i takich: schemat + host + port. http://example.comi https://example.comnie są tego samego pochodzenia (różne systemy). http://example.comi http://www.example.comnie są tego samego pochodzenia (różne hosty). http://example.comi http://example.com:8080nie są tego samego pochodzenia (różne porty). HTH. :-)
TJ Crowder
133

W rzeczywistości Opera nie ma limitu 5 MB. Oferuje zwiększenie limitu, ponieważ aplikacje wymagają więcej. Użytkownik może nawet wybrać „Nieograniczone miejsce na dane” dla domeny.

Możesz łatwo przetestować limity / kwoty localStorage.

Tom Adler
źródło
50
Nie powoduje już awarii Chrome ... Ciekawe: 5 MB to 2,5 miliona znaków w Chrome. Najwyraźniej UFT16 jest używany do localStore.
Felix Alcala,
1
@ FelixAlcala Niestety, powoduje awarię Chrome 15.0.874.54 beta na Mac OS X. Miałem awarię przy 1.500.000 znaków.
Ivan Vučica
W moim urządzeniu rozbił się chrom, zresetowałem też bckground, ale nie jestem zaskoczony, że mój telefon ma tak mało pamięci RAM, że nie jest w stanie obsłużyć głupiej aplikacji FLASHLIGHT, gdy chrom jest otwarty.
Jack
6
@FelixAlcala - W rzeczywistości JavaScript udostępnia UCS-2. Chociaż jest podobny do UFT16tego, istnieją pewne bardzo ważne różnice ... głównie dotyczące tego, że UCS-2 wyprzedza UFT.
Jeremy J Starcher
@FelixAlcala Czy uważasz, że wyświetlanie liczby znaków oraz ekwiwalentu rozmiaru dysku (np. 2700 KB ~ 5274 KB) jest dobrym pomysłem?
AJ Hsu
76

Oto prosty skrypt do ustalenia limitu:

if (localStorage && !localStorage.getItem('size')) {
    var i = 0;
    try {
        // Test up to 10 MB
        for (i = 250; i <= 10000; i += 250) {
            localStorage.setItem('test', new Array((i * 1024) + 1).join('a'));
        }
    } catch (e) {
        localStorage.removeItem('test');
        localStorage.setItem('size', i - 250);            
    }
}

Oto sedno , JSFiddle i post na blogu .

Skrypt będzie testował ustawienie coraz większych ciągów tekstu, dopóki przeglądarka nie zgłosi wyjątku. W tym momencie wyczyści dane testowe i ustawi klucz wielkości w localStorage, przechowując rozmiar w kilobajtach.

cdmckay
źródło
1
Fajne rozwiązanie. Znalazłem ten jeden liniowiec , co myślisz?
brasofilo
2
@brasofilo Myślę, że jedna linijka zakłada, że ​​masz 5 MB, a następnie odejmuje używaną ilość.
cdmckay
Ooook, pewnie strzał. Problem, który mam z twoim kodem, nie jest w stanie uzyskać poprawnych wyników z Prawidłowym sposobem konwersji rozmiaru w bajtach na KB, MB, GB w JavaScript ... Poprawię to jutro, ale jeśli możesz rzucić okiem, docenione.
brasofilo
1
poprawiłem wydajność i jakość tej odpowiedzi tutaj
smnbbrv
Jest rok 2020 i ta odpowiedź działa doskonale zarówno na waniliowym Chrome, jak i Firefox na Win10, dając rozmiar = 5000.
A. Chiesa
34

Znajdź maksymalną długość pojedynczego ciągu, w którym można przechowywać localStorage

Ten fragment znajdzie maksymalną długość ciągu, który można przechowywać w localStoragedomenie.

//Clear localStorage
for (var item in localStorage) delete localStorage[item];

window.result = window.result || document.getElementById('result');

result.textContent = 'Test running…';

//Start test
//Defer running so DOM can be updated with "test running" message
setTimeout(function () {

    //Variables
    var low = 0,
        high = 2e9,
        half;

    //Two billion may be a little low as a starting point, so increase if necessary
    while (canStore(high)) high *= 2;


    //Keep refining until low and high are equal
    while (low !== high) {
        half = Math.floor((high - low) / 2 + low);

        //Check if we can't scale down any further
        if (low === half || high === half) {
            console.info(low, high, half);
            //Set low to the maximum possible amount that can be stored 
            low = canStore(high) ? high : low;
            high = low;
            break;
        }


        //Check if the maximum storage is no higher than half
        if (storageMaxBetween(low, half)) {
            high = half;
            //The only other possibility is that it's higher than half but not higher than "high"
        } else {
            low = half + 1;
        }

    }

    //Show the result we found!
    result.innerHTML = 'The maximum length of a string that can be stored in localStorage is <strong>' + low + '</strong> characters.';

    //Functions
    function canStore(strLen) {
        try {
            delete localStorage.foo;
            localStorage.foo = Array(strLen + 1).join('A');
            return true;
        } catch (ex) {
            return false;
        }
    }


    function storageMaxBetween(low, high) {
        return canStore(low) && !canStore(high);
    }

}, 0);
<h1>LocalStorage single value max length test</h1>

<div id='result'>Please enable JavaScript</div>

Zauważ, że długość łańcucha jest ograniczona w JavaScript; jeśli chcesz wyświetlić maksymalną ilość danych, które mogą być przechowywane localStoragebez ograniczenia do jednego ciągu, możesz użyć kodu z tej odpowiedzi .

Edycja: Fragmenty stosu nie obsługują localStorage, więc tutaj jest link do JSFiddle .

Wyniki

Chrome (45.0.2454.101): 5242878 znaków
Firefox (40.0.1): 5242883 znaków
Internet Explorer (11.0.9600.18036) :16386 122066 122070 znaków

Otrzymuję różne wyniki dla każdego uruchomienia w Internet Explorerze.

użytkownik2428118
źródło
1
Zabawne, ale twój prosty test zatrzymał mój dość potężny system, gdy testowałem w przeglądarce Edge (na Win 10) po ~ 1 minucie działania. Więc nie mogę dołączyć nowych danych do twoich wyników))
vatavale
33

Przeglądarki mobilne:

Browser    | Chrome    | Android Browser    | Firefox     | iOS Safari
Version    | 40        | 4.3                | 34          | 6-8
Available  | 10MB      | 2MB                | 10MB        | 5MB

Przeglądarki stacjonarne:

Browser    | Chrome   | Opera    | Firefox    | Safari      | IE
Version    | 40       | 27       | 34         | 6-8         | 9-11
Available  | 10MB     | 10MB     | 10MB       | 5MB         | 10MB

Link referencyjny

Behnam Mohammadi
źródło
6
Skąd pochodzą liczby?
MrD
23
@BehnamMohammadi, czy możesz dodać odniesienie do tego, skąd masz to kompletność
Chris Lang
1
I nigdy nie podano żadnych odniesień. Ale dla potomności te liczby się nieco zmieniają. Powinniśmy zaktualizować to więcej przeglądarek i bieżące informacje.
Malavos
3
@ChrisLang dodał link
Behnam Mohammadi
1
@Malavos dodał link
Behnam Mohammadi
13

Nie chcesz łączyć dużych obiektów w pojedynczy wpis localStorage. Byłoby to bardzo nieefektywne - całość musiałaby zostać przeanalizowana i ponownie zakodowana za każdym razem, gdy wprowadzono drobne zmiany w szczegółach. Ponadto JSON nie jest w stanie obsłużyć wielu odsyłaczy w strukturze obiektu i usuwa wiele szczegółów, np. Konstruktor, nienumeryczne właściwości tablic, co znajduje się we wpisie rzadkim itp.

Zamiast tego możesz użyć Rhaboo . Przechowuje duże obiekty przy użyciu wielu wpisów localStorage, dzięki czemu można szybko wprowadzać małe zmiany. Przywrócone obiekty są znacznie dokładniejszymi kopiami zapisanych, a interfejs API jest niezwykle prosty. Na przykład:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

BTW, napisałem to.

Adrian May
źródło
1
Dzięki Martin. Równie dobrze możesz sprawdzić moje repozytorium „evon”. Obecnie jest to tylko serializator, a atrament jest bardzo mokry, ale jest szybszy niż rababoo i równie wszechstronny. Rhaboo zostanie wkrótce przekonwertowane do użytku wewnętrznego.
Adrian,
7
Przydatne, ale nie sądzę, że rozwiązuje to pytanie „Jaki jest maksymalny rozmiar localStorage;” twoją odpowiedź można poprawić, podając, co się dzieje, gdy biblioteka próbuje zapisać coś poza limitem wielkości i jak na to zareagować.
Chris Moschini
6

Wykonuję następujące czynności:

getLocalStorageSizeLimit = function () {

    var maxLength = Math.pow(2,24);
    var preLength = 0;
    var hugeString = "0";
    var testString;
    var keyName = "testingLengthKey";

    //2^24 = 16777216 should be enough to all browsers
    testString = (new Array(Math.pow(2, 24))).join("X");

    while (maxLength !== preLength) {
        try  {
            localStorage.setItem(keyName, testString);

            preLength = testString.length;
            maxLength = Math.ceil(preLength + ((hugeString.length - preLength) / 2));

            testString = hugeString.substr(0, maxLength);
        } catch (e) {
            hugeString = testString;

            maxLength = Math.floor(testString.length - (testString.length - preLength) / 2);
            testString = hugeString.substr(0, maxLength);
        }
    }

    localStorage.removeItem(keyName);

    maxLength = JSON.stringify(this.storageObject).length + maxLength + keyName.length - 2;

    return maxLength;
};
Itay Merchav
źródło
5
Maroun Maroun: Sprawdź ponownie post, autor podał kod, aby programowo sprawdzić maksymalny rozmiar lokalnego magazynu. To wydaje się być poprawną odpowiedzią, a nie kolejnym pytaniem.
Arend
Wykonanie tego kodu powoduje błąd „Niedozwolony zwrot” w Chrome w momencie pisania
DrewT
6

Naprawdę podoba mi się odpowiedź cdmckay , ale sprawdzanie rozmiaru w czasie rzeczywistym nie wygląda dobrze: jest po prostu zbyt wolne (dla mnie 2 sekundy). Jest to ulepszona wersja, która jest znacznie szybsza i dokładniejsza, również z opcją wyboru, jak duży może być błąd (domyślnie 250,000, im mniejszy błąd - tym dłuższe jest obliczenie):

function getLocalStorageMaxSize(error) {
  if (localStorage) {
    var max = 10 * 1024 * 1024,
        i = 64,
        string1024 = '',
        string = '',
        // generate a random key
        testKey = 'size-test-' + Math.random().toString(),
        minimalFound = 0,
        error = error || 25e4;

    // fill a string with 1024 symbols / bytes    
    while (i--) string1024 += 1e16;

    i = max / 1024;

    // fill a string with 'max' amount of symbols / bytes    
    while (i--) string += string1024;

    i = max;

    // binary search implementation
    while (i > 1) {
      try {
        localStorage.setItem(testKey, string.substr(0, i));
        localStorage.removeItem(testKey);

        if (minimalFound < i - error) {
          minimalFound = i;
          i = i * 1.5;
        }
        else break;
      } catch (e) {
        localStorage.removeItem(testKey);
        i = minimalFound + (i - minimalFound) / 2;
      }
    }

    return minimalFound;
  }
}

Testować:

console.log(getLocalStorageMaxSize()); // takes .3s
console.log(getLocalStorageMaxSize(.1)); // takes 2s, but way more exact

Działa to znacznie szybciej w przypadku błędu standardowego; w razie potrzeby może być znacznie dokładniejszy.

smnbbrv
źródło
6

Skondensowałem test binarny do tej funkcji, której używam:

function getStorageTotalSize(upperLimit/*in bytes*/) {
    var store = localStorage, testkey = "$_test"; // (NOTE: Test key is part of the storage!!! It should also be an even number of characters)
    var test = function (_size) { try { store.removeItem(testkey); store.setItem(testkey, new Array(_size + 1).join('0')); } catch (_ex) { return false; } return true; }
    var backup = {};
    for (var i = 0, n = store.length; i < n; ++i) backup[store.key(i)] = store.getItem(store.key(i));
    store.clear(); // (you could iterate over the items and backup first then restore later)
    var low = 0, high = 1, _upperLimit = (upperLimit || 1024 * 1024 * 1024) / 2, upperTest = true;
    while ((upperTest = test(high)) && high < _upperLimit) { low = high; high *= 2; }
    if (!upperTest) {
        var half = ~~((high - low + 1) / 2); // (~~ is a faster Math.floor())
        high -= half;
        while (half > 0) high += (half = ~~(half / 2)) * (test(high) ? 1 : -1);
        high = testkey.length + high;
    }
    if (high > _upperLimit) high = _upperLimit;
    store.removeItem(testkey);
    for (var p in backup) store.setItem(p, backup[p]);
    return high * 2; // (*2 because of Unicode storage)
}

Tworzy kopię zapasową zawartości przed testowaniem, a następnie przywraca ją.

Jak to działa: podwaja rozmiar, dopóki limit nie zostanie osiągnięty lub test się nie powiedzie. Następnie zapisuje połowę odległości między niskim a wysokim i odejmuje / dodaje za każdym razem połowę połowy (odejmuje w przypadku niepowodzenia i dodaje w przypadku sukcesu); szlifowanie do właściwej wartości.

upperLimitDomyślnie jest to 1 GB i ogranicza jedynie ekspansję wykładniczą w górę przed rozpoczęciem wyszukiwania binarnego. Wątpię, czy trzeba to zmienić, ale zawsze myślę o przyszłości. ;)

W Chrome:

> getStorageTotalSize();
> 10485762
> 10485762/2
> 5242881
> localStorage.setItem("a", new Array(5242880).join("0")) // works
> localStorage.setItem("a", new Array(5242881).join("0")) // fails ('a' takes one spot [2 bytes])

IE11, Edge i FireFox również zgłaszają ten sam maksymalny rozmiar (10485762 bajtów).

James Wilkins
źródło
1
(I nie zapomnij localStorage.Clear()przed i po testach
simonmysun
5

W nowoczesnych przeglądarkach możesz użyć następującego kodu, aby efektywnie sprawdzić limit miejsca (całkowity i zajęty) w czasie rzeczywistym:

if ('storage' in navigator && 'estimate' in navigator.storage) {
        navigator.storage.estimate()
            .then(estimate => {
                console.log("Usage (in Bytes): ", estimate.usage,
                            ",  Total Quota (in Bytes): ", estimate.quota);
            });
}
Abhishek
źródło
Nie działa dobrze w Chrome. Usage (in Bytes): 647 , Total Quota (in Bytes): 32901464711 To źle: całkowity możliwy rozmiar to w rzeczywistości 10485762.
James Wilkins
1

Kiedyś opracowałem rozszerzenie Chrome (przeglądarka na komputer) i przetestowałem z tego powodu maksymalny rozmiar magazynu lokalnego .

Moje wyniki:

Ubuntu 18.04.1 LTS (64-bit)
Chrome 71.0.3578.98 (Official Build) (64-bit)
Local Storage content size 10240 KB (10 MB)

Więcej niż 10240 KBużycie zwróciło mi błąd:

Niezabezpieczony DOMException: Nie można wykonać „setItem” w „Storage”: Ustawienie wartości „notes” przekroczyło limit.

smokehill
źródło
0

Napisałem ten prosty kod, który testuje rozmiar localStorage w bajtach.

https://github.com/gkucmierz/Test-of-localStorage-limits-quota

const check = bytes => {
  try {
    localStorage.clear();
    localStorage.setItem('a', '0'.repeat(bytes));
    localStorage.clear();
    return true;
  } catch(e) {
    localStorage.clear();
    return false;
  }
};

Strony Github:

https://gkucmierz.github.io/Test-of-localStorage-limits-quota/

Te same wyniki mam na Chrome Desktop, Opera, Firefox, odważny i mobilny Chrome, który wynosi ~ 5 MB

wprowadź opis zdjęcia tutaj

I o połowę mniejszy wynik w safari ~ 2 MB

wprowadź opis zdjęcia tutaj

gkucmierz
źródło