Cách tìm kích thước của localStorage


117

Tôi hiện đang phát triển một trang web sẽ sử dụng localStorage của HTML5. Tôi đã đọc tất cả về giới hạn kích thước cho các trình duyệt khác nhau. Tuy nhiên, tôi chưa thấy gì về cách tìm ra kích thước hiện tại của một phiên bản localStorage. Câu hỏi này dường như chỉ ra rằng JavaScript không có một cách xây dựng để hiển thị kích thước cho một biến nhất định. LocalStorage có thuộc tính kích thước bộ nhớ mà tôi chưa thấy không? Có cách nào dễ dàng để làm điều này mà tôi đang thiếu không?

Trang web của tôi nhằm cho phép người dùng nhập thông tin ở chế độ 'ngoại tuyến', vì vậy việc có thể đưa ra cảnh báo cho họ khi bộ nhớ gần đầy là rất quan trọng.


Câu trả lời:


219

Thực thi đoạn mã này trong bảng điều khiển JavaScript (phiên bản một dòng):

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

Cùng một đoạn mã trong nhiều dòng để dễ đọc

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

hoặc thêm văn bản này vào trường 'vị trí' của dấu trang để sử dụng thuận tiện

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

PS Snippets được cập nhật theo yêu cầu trong bình luận. Bây giờ tính toán bao gồm độ dài của chính khóa. Mỗi độ dài được nhân với 2 vì char trong javascript lưu trữ dưới dạng UTF-16 (chiếm 2 byte)

PPS sẽ hoạt động trên cả Chrome và Firefox.


8
Dán cái này vào bảng điều khiển để xem tổng: var t = 0; for (var x in localStorage) {t + = (((localStorage [x] .length * 2))); } console.log (t / 1024 + "KB");
Henry

5
@Micah Javascript sử dụng UTF16 nội bộ, vì vậy vì mỗi ký tự được lưu trữ dưới dạng hai byte, bạn cần nhân số ký tự với hai để có được không gian thực sự được sử dụng. (Bạn đã có thể đã phát hiện ra điều này, nhưng tôi nghĩ rằng nó đáng chú ý ở đây chỉ dành riêng cho bất cứ ai khác có cùng một câu hỏi)
Rebecka

2
@Serge, câu trả lời này được bình chọn nhiều nhất do đó đăng ở đây var t = 0; for(var x in localStorage) { t += (x.length + localStorage[x].length) * 2; } console.log(t/1024+ " KB");
Mihir

17
Dưới đây là một phiên bản sửa đổi mà chiếm NaN cũng như: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");
Mario Sannum

1
Có một lỗi trong bookmarklet. Bạn đang sử dụng các biến được gạch dưới trong mã chính và tên bình thường trong bookmarklet. Dấu gạch dưới đơn _xphá vỡ nó. Đơn giản chỉ cần xóa dấu gạch dưới.
Soul Reaver

46

Ngoài những gì @Shourav đã nói ở trên, tôi đã viết một hàm nhỏ có thể lấy chính xác tất cả các localStoragekhóa của bạn (cho miền hiện tại) và tính toán kích thước kết hợp để bạn biết chính xác localStorageđối tượng của bạn chiếm bao nhiêu bộ nhớ :

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

Của tôi đã trả lại: "30.896484375 KB"


1
Cảm ơn @tennisgent. Của tôi hoạt động cho IE11, FF> 26 và cả Chrome.
Akki922234

18

IE có thuộc tính Không gian còn lại của đối tượng Lưu trữ. Các trình duyệt khác không có trình duyệt tương đương tại thời điểm này.

Tôi tin rằng dung lượng mặc định là 5MB, mặc dù tôi chưa thử nghiệm nó.


1
Đây là sản phẩm duy nhất của IE
jas- 29/09

là giới hạn 5 mb cho mỗi trang web hay tổng thể cho tất cả các trang web?
divyenduz

@divyenduz trên mỗi trang web, tôi nghĩ
Adam

2
Lưu ý rằng thuộc tính localStorage.remainingSpace trả về số ký tự UTF-16 còn lại được phép cho đối tượng lưu trữ. KHÔNG phải là kích thước còn lại tính bằng byte. Tham khảo
Mihir

14

Đây là một ví dụ đơn giản về cách thực hiện việc này và sẽ hoạt động với mọi trình duyệt

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

bạn không cần một * 8 ở đâu đó trong đó?
George Mauer

1
Phụ thuộc vào bộ ký tự (tức là utf8, v.v.) mà không tính đến
jas-

Điều này cung cấp kích thước tính bằng byte hay bit?
JamesTheAwesomeDude

6
Ví dụ này giả định không chính xác rằng localStorage có cùng một giới hạn cố định là 5MB (5 * 1024 * 1024) trong mỗi trình duyệt.
Victor

Đó là theo thông số được đưa ra bởi w3c.
jas-

13

Hy vọng điều này sẽ giúp ai đó.

Vì Jas- example trên jsfiddle không hoạt động với tôi nên tôi đã đưa ra giải pháp này. (cảm ơn Serge Seletskyy và Shourav vì những bit của họ mà tôi đã sử dụng trong đoạn mã bên dưới)

Dưới đây là hàm có thể được sử dụng để kiểm tra xem còn bao nhiêu dung lượng cho localStorage và (nếu bất kỳ khóa nào đã có trong lS) còn bao nhiêu dung lượng.

Nó hơi thô bạo nhưng nó hoạt động trên hầu hết mọi trình duyệt, ngoại trừ Firefox. Trong FF dành cho máy tính để bàn, phải mất nhiều thời gian (4-5 phút) để hoàn thành, và trên Android thì nó chỉ bị treo.

Bên dưới chức năng là một bản tóm tắt ngắn về các thử nghiệm mà tôi đã thực hiện trong các trình duyệt khác nhau trên các nền tảng khác nhau. Thưởng thức!

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
}

Và như đã hứa ở trên, một số thử nghiệm trên các trình duyệt khác nhau:

GalaxyTab 10.1

  • Maxthon Pad 1.7 ~ 1130ms 5Mb
  • Firefox 20.0 (Beta 20.0) bị lỗi cả hai
  • Chrome 25.0.1364.169 ~ 22250ms / 5Mb
  • Gốc (xác định là Safari 4.0 / Webkit534.30) ~ 995ms / 5Mb

iPhone 4s iOS 6.1.3

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

MacBook Pro OSX 1.8.3 (Core 2 Duo 2.66 bộ nhớ 8Gb)

  • Safari 6.0.3 ~ 105ms / 5Mb
  • Chrome 26.0.1410.43 ~ 3400ms / 5Mb
  • Firefox 20.0 300150ms (!) / 10Mb (sau khi phàn nàn về việc tập lệnh chạy quá lâu)

iPad 3 iOS 6.1.3

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

Windows 7 -64b (Core 2 Duo 2.93 bộ nhớ 6Gb)

  • Safari 5.1.7 ~ 80ms / 5Mb
  • Chrome 26.0.1410.43 ~ 1220ms / 5Mb
  • Firefox 20.0 228500ms (!) / 10Mb (sau khi phàn nàn về việc tập lệnh chạy quá lâu)
  • IE9 ~ 17900ms /9,54Mb (nếu có bất kỳ bảng điều khiển nào trong mã không hoạt động cho đến khi DevTools được mở)
  • Opera 12.15 ~ 4212ms / 3.55Mb (đây là khi 5Mb được chọn, nhưng Opera hỏi rất hay nếu chúng ta muốn tăng lượng lS, rất tiếc là nó bị treo nếu tiến hành thử nghiệm một vài lần liên tiếp)

Thắng 8 (Dưới các điểm 8)

  • IE10 ~ 7850ms /9,54Mb

Những thí nghiệm tuyệt vời. Tuy nhiên, tôi tìm thấy array.forEach()mã của bạn, vì tôi biết nó không tồn tại trong IE, bạn có tự thực hiện không? Làm cách nào để bạn đo lường đóng góp của nó vào độ trễ tổng thể?
Evi Song

Cảm ơn, tôi có thể làm lại chúng vì đã qua một thời gian so với các thử nghiệm ban đầu. Đối với forEach(). Không, tôi đã không tự thực hiện nó, tôi đã sử dụng cổ phiếu Array.prototype.forEach(). Theo Mozilla Developer Network hay còn gọi là MDN từ IE9, nó có hỗ trợ riêng.
Jakub Gadkowski

Cảm ơn. Kiến thức của tôi cần được làm mới. Sau này, tôi sẽ sử dụng Array.prototype.forEach()càng nhiều càng tốt nếu dự án của tôi không hỗ trợ các phiên bản IE sớm.
Evi Song

Mã có thể được thực hiện nhanh hơn đáng kể (~ 2500ms trong Firefox, ~ 700ms trong Chrome): chia whilevòng lặp thành hai phần, phần đầu tiên giống như trong stackoverflow.com/a/3027249/1235394 lấp đầy localStorage với các khối dữ liệu đang tăng theo cấp số nhân, sau đó là phần thứ hai với các khối nhỏ có kích thước cố định để lấp đầy bộ nhớ. Trang kiểm tra: jsfiddle.net/pqpps3tk/1
Victor

IE10 Rocks .. Tuy nhiên, trình duyệt nhanh nhất để tải Chrome :)
Ruslan Abuzant

11

Bạn có thể lấy kích thước hiện tại của dữ liệu lưu trữ cục bộ bằng cách sử dụng chức năng Blob. Điều này có thể không hoạt động trong các trình duyệt cũ, hãy kiểm tra hỗ trợ cho new BlobObject.values()cẩn thận.

Thí dụ:

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

Object.values ​​() biến đối tượng localStorage thành một mảng. Blob biến mảng thành dữ liệu thô.


3
Tôi nghĩ rằng Blobkhông hạn chế mã hóa chuỗi thành UTF-16, vì vậy đây thực sự có thể là phương pháp đáng tin cậy nhất. new Blob(['X']).size;= 1 trong khi new Blob(['☃']).size(U + 2603 / ký tự người tuyết) ==> 3. Các giải pháp dựa trên String.prototype.lengthkhông tính đến điều này (xử lý "ký tự") trong khi hạn ngạch / giới hạn bộ nhớ có thể xảy ra (xử lý theo byte) và tôi có thể tưởng tượng điều này dẫn đến bất ngờ, chẳng hạn như khi lưu trữ các ký tự không phải tiếng Anh / ASCII.
iX3,

Tôi đã sử dụng câu trả lời của Jed để tính toán kích thước localStorage với độ dài chuỗi để kiểm tra giải pháp Blob trong Chrome & FF. Trong thử nghiệm đầu tiên, tôi đã điền localStorage bằng ký hiệu '1'. trong thử nghiệm thứ hai, tôi đã điền localStorage bằng dấu '' ☃ '' có kích thước lớn hơn trong đối tượng Blob. Trong cả hai trường hợp, tôi nhận được chính xác cùng độ dài localStorage tối đa. Vì vậy kích thước Blob của các ký tự không ảnh hưởng đến giới hạn localStorage. Đó là lý do tại sao Blob không nên được sử dụng cho mục đích này.
Vincente

6

Bạn có thể tính toán lưu trữ cục bộ của mình bằng các phương pháp sau:

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

Cuối cùng kích thước tính bằng byte sẽ được đăng nhập trong trình duyệt.


4

Tôi sẽ sử dụng mã @tennisgen để lấy tất cả và đếm nội dung, nhưng tôi tự đếm các khóa:

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

3

Cách tôi giải quyết vấn đề này là tạo các hàm để tìm ra dung lượng đã sử dụng và dung lượng còn lại trong Local Storage và sau đó là một hàm gọi các hàm đó để xác định dung lượng lưu trữ tối đa.

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

Array.join là một kẻ giết người thực hiện, tốt hơn sử dụng String.repeat nếu có (điều đó có nghĩa ở khắp mọi nơi ngoại trừ IE)
pkExec

2

Ngoài câu trả lời của @ serge được bình chọn nhiều nhất ở đây, kích thước của các phím cũng cần được xem xét. Mã bên dưới sẽ thêm kích thước của các khóa được lưu trữ tronglocalStorage

var t = 0; 
for (var x in localStorage) { 
    t += (x.length + localStorage[x].length) * 2; 
} 
console.log((t / 1024) + " KB");

Tôi đã tìm thấy rằng Firefox lợi nhuận undefinedcho các mục lengthtrong một số trường hợp, vì vậy tôi đã thêm một điều kiện để việc bổ sung: t += (x.length + (this.storage[x].length ? this.storage[x].length : 0)) * 2;.
camilokawerin

@camilokawerin, không nên trừ khi một giá trị không xác định được lưu trong bộ nhớ, bởi vì Chuỗi là loại duy nhất được hỗ trợ với localStorage và Chuỗi có thuộc tính Độ dài. Bạn có thể đăng một số ví dụ trên jsfiddle hoặc một cái gì đó tương tự?
Mihir

1

Như thông số kỹ thuật, mỗi ký tự của một chuỗi là 16 bit.

Nhưng việc kiểm tra bằng chrome (Cài đặt> Cài đặt nội dung> Cookie & dữ liệu trang web) cho chúng tôi thấy rằng việc khởi tạo localStorage mất 3kB (kích thước chi phí)

Và kích thước dữ liệu được lưu trữ tuân theo mối quan hệ này (chính xác đến 1kB)
3 + ((localStorage.x.length * 16) / (8 * 1024)) kB

trong đó localStorage.x là chuỗi lưu trữ của bạn.


0

// Bộ nhớ chiếm cả khóa và giá trị nên Mã cập nhật.

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

0

Vâng, câu hỏi này đã được hỏi giống như 10 năm trước. Nhưng đối với những người quan tâm (như tôi, vì tôi đang xây dựng một trình soạn thảo văn bản ngoại tuyến giúp lưu dữ liệu bằng bộ nhớ cục bộ) và mê lập trình, bạn có thể sử dụng một cái gì đó đơn giản như sau:

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

Cách tốt nhất để lấp đầy dung lượng lưu trữ là xem cài đặt trang web (giả sử, nếu bạn đã lưu trữ hình ảnh trong bộ nhớ cục bộ). Ít nhất trong chrome, bạn có thể thấy số lượng byte được sử dụng (tức là: 1222 byte). Tuy nhiên, các cách tốt nhất để xem bộ nhớ cục bộ đầy với js đã được đề cập ở trên, vì vậy hãy sử dụng chúng.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.