Berapa ukuran maksimal dari nilai localStorage?

542

Karena localStorage(saat ini) hanya mendukung string sebagai nilai-nilai, dan untuk melakukan itu objek-objek tersebut perlu dirubah (disimpan sebagai JSON-string) sebelum dapat disimpan, apakah ada batasan yang ditentukan mengenai panjang nilai.

Adakah yang tahu kalau ada definisi yang berlaku untuk semua browser?

Codekie
sumber
15
Saya pikir tidak ada yang benar-benar menjawab pertanyaan "panjang maks per nilai".
Pete Alvin
@PeteAlvin Saya baru saja menjawab pertanyaan .
user2428118
@PeteAlvin Seseorang menjawabnya pada tahun 2015. Jawaban yang lain membahas batas pada ukuran total, tetapi bukan batas pada ukuran per nilai .
Ali

Jawaban:

420

Mengutip dari artikel Wikipedia tentang Penyimpanan Web :

Penyimpanan web dapat dilihat secara sederhana sebagai peningkatan cookie, memberikan kapasitas penyimpanan yang jauh lebih besar ( 10 MB per asal di Google Chrome ( https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh ), Mozilla Firefox , dan Opera; 10 MB per area penyimpanan di Internet Explorer ) dan antarmuka terprogram yang lebih baik.

Dan juga mengutip dari artikel John Resig [diposting Januari 2007]:

Ruang penyimpanan

Tersirat bahwa, dengan DOM Storage, Anda memiliki ruang penyimpanan yang jauh lebih besar daripada batasan agen pengguna tipikal yang dikenakan pada Cookie. Namun, jumlah yang disediakan tidak ditentukan dalam spesifikasi, juga tidak berarti disiarkan oleh agen pengguna.

Jika Anda melihat kode sumber Mozilla, kita dapat melihat bahwa 5120KB adalah ukuran penyimpanan default untuk seluruh domain. Ini memberi Anda lebih banyak ruang untuk bekerja daripada cookie 2KB pada umumnya.

Namun, ukuran area penyimpanan ini dapat disesuaikan oleh pengguna (sehingga area penyimpanan 5MB tidak dijamin, juga tidak tersirat) dan agen pengguna (Opera, misalnya, hanya dapat menyediakan 3MB - tetapi hanya waktu yang akan memberi tahu. )

Daniel Vassallo
sumber
28
@Cupidvogel tidak, itu artinya masing-masing domain( origin) dapat menyimpan 5MB pada setiap klien. Data disimpan di mesin klien - sama sekali tidak localStoragemekanisme berinteraksi di klien.
DanielB
6
Tidak, saya hanya ingin memastikan bahwa data yang sama dapat diakses di beberapa halaman untuk domain yang sama. Seringkali saya menemukan frasa domain dan halaman dieja secara sinonim, jadi hanya ingin tahu pasti!
SexyBeast
9
Namun, adakah batasan pada nilai tunggal ? (Jika saya memiliki banyak bendera untuk disimpan, seberapa amankah untuk menyimpannya sebagai JSON di satu properti?)
phtrivier
5
Saya memiliki Safari pada 5MB dan Chrome 39 pada 10MB (tidak yakin kapan itu ditingkatkan dari 5MB) Lihat artikel ini html5rocks.com/en/tutorials/offline/quota-research
Ally
18
@Cupidvogel: Tidak, ini bukan berdasarkan domain, ini berdasarkan asal , karena istilah ini digunakan berhadapan dengan Kebijakan Asal yang Sama dan seperti: skema + host + port. http://example.comdan https://example.combukan asal yang sama (skema berbeda). http://example.comdan http://www.example.combukan asal yang sama (host berbeda). http://example.comdan http://example.com:8080bukan asal yang sama (port yang berbeda). HTH. :-)
TJ Crowder
134

Sebenarnya Opera tidak memiliki batas 5MB. Ia menawarkan untuk meningkatkan batas karena aplikasi membutuhkan lebih banyak. Pengguna bahkan dapat memilih "Penyimpanan tidak terbatas" untuk domain.

Anda dapat dengan mudah menguji batas penyimpanan / kuota local sendiri.

Tom Adler
sumber
50
Tidak lagi merusak Chrome ... Poin menarik: 5MB sama dengan 2,5 Juta karakter di Chrome. Jadi ternyata, UFT16 digunakan untuk localStore.
Felix Alcala
1
@FelixAlcala Sayangnya, crash Chrome 15.0.874.54 beta di Mac OS X. Saya mengalami crash di 1.500.000 karakter.
Ivan Vučica
Ini crash chrome pada perangkat saya, juga mengatur ulang bckground, meskipun tidak terkejut, ponsel saya memiliki RAM yang begitu kecil, tidak dapat menangani memiliki aplikasi FLASHLIGHT bodoh terbuka sementara chrome terbuka.
Jack
6
@FelixAlcala - Sebenarnya, JavaScript memaparkan UCS-2. Meskipun mirip dengan UFT16ada beberapa perbedaan yang sangat penting ... sebagian besar berputar di sekitar fakta bahwa UCS-2 mendahului UFT.
Jeremy J Starcher
@FelixAlcala Apakah menurut Anda menampilkan berapa banyak karakter serta ukuran disk yang setara (mis., 2.700 karakter ~ ~ 5.274 KB) adalah ide yang bagus?
AJ Hsu
76

Berikut ini skrip sederhana untuk mengetahui batasnya:

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

Inilah intisari , JSFiddle dan posting blog .

Script akan menguji pengaturan string teks yang semakin besar hingga browser melempar dan pengecualian. Pada titik itu akan menghapus data uji dan menetapkan kunci ukuran di penyimpanan lokal menyimpan ukuran dalam kilobyte.

cdmckay
sumber
1
Solusi keren Saya menemukan liner yang satu ini , bagaimana menurut Anda?
brasofilo
2
@ brasofilo Saya pikir satu liner mengasumsikan Anda memiliki 5MB dan kemudian kurangi jumlah yang digunakan.
cdmckay
Ooook, tembakan pasti. Masalah yang saya alami dengan kode Anda adalah tidak bisa mendapatkan hasil yang benar dengan cara yang benar untuk mengonversi ukuran dalam byte ke KB, MB, GB dalam Javascript ... Saya akan merevisi ini besok tetapi jika Anda dapat melihatnya, dihargai.
brasofilo
1
meningkatkan kinerja dan kualitas jawaban ini di sini
smnbbrv
Ini tahun 2020 dan jawaban ini berfungsi dengan baik pada vanilla Chrome dan Firefox pada Win10, memberikan ukuran = 5000.
A. Chiesa
34

Temukan panjang maksimum satu string yang dapat disimpan localStorage

Cuplikan ini akan menemukan panjang maksimum String yang dapat disimpan dalam localStorageper domain.

//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>

Perhatikan bahwa panjang string dibatasi dalam JavaScript; jika Anda ingin melihat jumlah maksimum data yang dapat disimpan localStorageketika tidak terbatas pada satu string, Anda dapat menggunakan kode dalam jawaban ini .

Sunting: Potongan Stack tidak mendukung localStorage, jadi di sini ada tautan ke JSFiddle .

Hasil

Chrome (45.0.2454.101): 5242878 karakter
Firefox (40.0.1): 5242883 karakter
Internet Explorer (11.0.9600.18036) :16386 122066 122070 karakter

Saya mendapatkan hasil berbeda pada setiap proses di Internet Explorer.

pengguna2428118
sumber
1
Lucu, tetapi tes sederhana Anda menghentikan sistem saya yang cukup kuat ketika saya uji di browser Edge (pada Win 10) setelah ~ 1 menit berjalan. Jadi saya tidak bisa menambahkan data baru ke hasil Anda))
vatavale
33

Browser seluler:

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

Browser desktop:

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

Tautan Referensi

Behnam Mohammadi
sumber
6
Dari mana angka itu berasal?
MrD
23
@BehnamMohammadi dapatkah Anda menambahkan referensi dari mana Anda mendapatkannya dari kelengkapan ini
Chris Lang
1
Dan tidak ada referensi yang pernah diisi. Tetapi untuk anak cucu, angka-angka ini sedikit berubah. Kita harus memperbarui ini dengan lebih banyak peramban dan info terkini.
Malavos
3
@ChrisLang menambahkan tautan
Behnam Mohammadi
1
@Malavos menambahkan tautan
Behnam Mohammadi
13

Anda tidak ingin merangkai objek besar menjadi satu entri Penyimpanan lokal. Itu akan sangat tidak efisien - semuanya harus diurai dan dikodekan ulang setiap kali beberapa perubahan detail kecil. Juga, JSON tidak dapat menangani banyak referensi silang dalam struktur objek dan menghapus banyak detail, misalnya konstruktor, properti array non-numerik, apa yang ada di entri jarang, dll.

Sebagai gantinya, Anda bisa menggunakan Rhaboo . Ini menyimpan objek besar menggunakan banyak entri Penyimpanan lokal sehingga Anda dapat membuat perubahan kecil dengan cepat. Objek yang dipulihkan adalah salinan yang jauh lebih akurat dari yang disimpan dan API sangat sederhana. Misalnya:

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, saya menulisnya.

Adrian May
sumber
1
Terima kasih Martin. Anda mungkin juga memeriksa repo 'evon' saya juga. Ini hanya serialiser sekarang dan tintanya sangat basah, tetapi lebih cepat dari rhaboo dan juga serbaguna. Rhaboo akan segera dikonversi untuk menggunakannya secara internal.
Adrian
7
Berguna tapi saya tidak berpikir ini menjawab pertanyaan "Berapa ukuran maksimum penyimpanan lokal;" jawaban Anda dapat ditingkatkan dengan menyatakan apa yang terjadi ketika perpustakaan ini mencoba untuk menyimpan sesuatu di luar batas ukuran, dan bagaimana bereaksi terhadapnya.
Chris Moschini
6

Saya melakukan hal berikut:

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
sumber
5
Maroun Maroun: Periksa kembali posnya, penulis telah memberikan kode untuk secara sistematis memeriksa ukuran maksimum penyimpanan lokal. Ini sepertinya jawaban yang valid, dan bukan pertanyaan lain.
Arend
Menjalankan kode ini menimbulkan kesalahan "Pernyataan pengembalian tidak sah" di Chrome, pada saat penulisan
DrewT
6

Saya sangat suka jawaban cdmckay , tetapi tidak terlalu bagus untuk memeriksa ukuran secara real time: terlalu lambat (2 detik untuk saya). Ini adalah versi yang disempurnakan, yang jauh lebih cepat dan lebih tepat, juga dengan opsi untuk memilih seberapa besar kesalahan (standar 250,000, semakin kecil kesalahan - semakin lama perhitungannya):

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

Untuk mengetes:

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

Ini bekerja lebih cepat secara dramatis untuk kesalahan standar; juga bisa jauh lebih tepat jika diperlukan.

smnbbrv
sumber
6

Saya telah menyingkat tes biner ke fungsi ini yang saya gunakan:

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

Itu juga mencadangkan konten sebelum pengujian, kemudian mengembalikannya.

Cara kerjanya: Ini menggandakan ukuran sampai batas tercapai atau tes gagal. Kemudian menyimpan setengah jarak antara rendah dan tinggi dan mengurangi / menambah setengah dari setiap kali (kurangi pada kegagalan dan tambahkan pada keberhasilan); mengasah ke nilai yang tepat.

upperLimitadalah 1GB secara default, dan hanya membatasi seberapa jauh untuk memindai secara eksponensial sebelum memulai pencarian biner. Saya ragu ini bahkan perlu diubah, tapi saya selalu berpikir ke depan. ;)

Di 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, dan FireFox juga melaporkan ukuran maks yang sama (10485762 bytes).

James Wilkins
sumber
1
(Dan jangan lupa localStorage.Clear()sebelum dan sesudah pengujian Anda
simonmysun
5

Anda dapat menggunakan kode berikut di browser modern untuk secara efisien memeriksa kuota penyimpanan (total & bekas) secara real-time:

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
sumber
Tidak berfungsi dengan baik untuk Chrome. Usage (in Bytes): 647 , Total Quota (in Bytes): 32901464711 Itu salah: ukuran total yang mungkin sebenarnya 10485762.
James Wilkins
1

Setelah saya mengembangkan ekstensi Chrome (browser desktop) dan menguji ukuran maksimum penyimpanan asli karena alasan ini.

Hasil saya:

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

Lebih dari 10240 KBpenggunaan mengembalikan saya kesalahan:

DOMException yang tidak tertangkap: Gagal menjalankan 'setItem' di 'Storage': Mengatur nilai 'catatan' melebihi kuota.

smokehill
sumber
0

Saya menulis kode sederhana ini yang menguji ukuran localStorage dalam byte.

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

Halaman Github:

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

Saya memiliki hasil yang sama pada chrome desktop, opera, firefox, berani dan mobile chrome yang ~ 5Mbytes

masukkan deskripsi gambar di sini

Dan setengahnya lebih kecil menghasilkan safari ~ 2Mbytes

masukkan deskripsi gambar di sini

gkucmierz
sumber