Tính toán việc sử dụng không gian localStorage


79

Tôi đang tạo một ứng dụng bằng trình soạn thảo Bespin và localStorage của HTML5. Nó lưu trữ tất cả các tệp cục bộ và trợ giúp về ngữ pháp, sử dụng JSLint và một số trình phân tích cú pháp khác cho CSS và HTML để hỗ trợ người dùng.

Tôi muốn tính toán lượng giới hạn localStorage đã được sử dụng và thực tế là bao nhiêu. Điều này có thể ngày hôm nay? Tôi đã suy nghĩ để không chỉ đơn giản tính toán các bit được lưu trữ. Nhưng rồi một lần nữa tôi không chắc còn điều gì nữa mà bản thân không thể đo lường được.



JavaScript / HTML5 localStorage usefull Functions: stackoverflow.com/q/34245593/4339170
CoderPi

Câu trả lời:


72

Bạn có thể có được một ý tưởng gần đúng bằng cách sử dụng các phương thức JSON để chuyển toàn bộ đối tượng localStorage thành một chuỗi JSON:

JSON.stringify(localStorage).length

Tôi không biết độ chính xác của từng byte sẽ như thế nào, đặc biệt là với vài byte đánh dấu được thêm vào nếu bạn đang sử dụng các đối tượng bổ sung - nhưng tôi nghĩ nó tốt hơn là nghĩ rằng bạn chỉ đẩy 28K và thay vào đó làm 280K (hoặc ngược lại).


4
Điều này thực sự đủ chính xác để làm việc với. Với localStorage đã được tối đa hóa trên Chrome 14, JSON.stringify (localStorage) .length === 2636625 hoặc 2,51448 MB, đủ gần ( dev-test.nemikor.com/web-storage/support-test ). Được sử dụng song song với thử {} catch {} và bạn đã có đủ để xây dựng một lớp trợ giúp.
Christopher

13
lưu ý rằng, như đã chỉ ra trong thử nghiệm bạn liên kết, đây là kích thước tính bằng ký tự chứ không phải byte: "Các chuỗi trong JavaScript là UTF-16, vì vậy mỗi ký tự yêu cầu hai byte bộ nhớ. Điều này có nghĩa là trong khi nhiều trình duyệt có 5 Giới hạn MB, bạn chỉ có thể lưu trữ 2,5 M ký tự. "
Mortimer

51

Tôi đã không tìm thấy một cách phổ biến để đạt được giới hạn còn lại trên các trình duyệt mà tôi cần, nhưng tôi đã phát hiện ra rằng khi bạn đạt đến giới hạn, sẽ có một thông báo lỗi bật lên. Điều này tất nhiên là khác nhau trong mỗi trình duyệt.

Để tối đa hóa nó, tôi đã sử dụng tập lệnh nhỏ này:

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

Từ đó tôi nhận được thông tin này:

Google Chrome

  • DOMException:
    • mã: 22
    • thông báo: "Không thực thi được 'setItem' trên 'Bộ nhớ': Đặt giá trị của 'dữ liệu' đã vượt quá hạn ngạch."
    • tên: "QuotaExceededError"

Mozilla Firefox

  • DOMException:
    • mã: 1014
    • thông báo: "Đã đạt đến kích thước tối đa của bộ nhớ liên tục"
    • tên: "NS_ERROR_DOM_QUOTA_REACHED"

Safari

  • DOMException:
    • mã: 22
    • thông báo: "QuotaExceededError: DOM Exception 22"
    • tên: "QuotaExceededError"

Internet Explorer, Edge (cộng đồng)

  • DOMException:
    • mã: 22
    • thông báo: "QuotaExceededError"
    • tên: "QuotaExceededError"

Giải pháp của tôi

Cho đến nay, giải pháp của tôi là thêm một cuộc gọi bổ sung mỗi khi người dùng lưu bất cứ thứ gì. Và nếu trường hợp ngoại lệ bị bắt thì tôi sẽ nói với họ rằng họ sắp hết dung lượng lưu trữ.


Chỉnh sửa: Xóa dữ liệu đã thêm

Tôi quên đề cập rằng để điều này thực sự hoạt động, bạn sẽ cần phải xóa DATAmục đã được đặt ban đầu. Sự thay đổi được phản ánh ở trên bằng cách sử dụng hàm removeItem () .


Rất tốt, giá trị của iđiều này là gì trong mỗi trường hợp?
artlung

20-21 tôi nghĩ. Bạn có thể tự chạy thử nghiệm nếu muốn.
JeroenEijkhof

IE: ABORT_ERR: 20 mã: 22 thông báo: "QuotaExceededError" tên: "QuotaExceededError"
Rui Lima

trong IE, mã của bạn tăng ngoại lệ trước khi kết thúc khoảng trắng: window.localStorage.remainingSpace: 805692 | window.localStorage.getItem ("DỮ LIỆU"). length: 4194304 | JSON.stringify (localStorage) .length: 4194315 | i: 22
Rui Lima

tốt sau đó tôi có thể bọc mã lưu trữ cục bộ trong thử khối bắt và cảnh báo người dùng trong khối bắt về kích thước vượt quá.
Nirus

26

IE8 triển khai thuộc remainingSpacetính cho mục đích này:

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

Thật không may, có vẻ như điều này không có sẵn trong các trình duyệt khác. Tuy nhiên, tôi không chắc liệu họ có triển khai một cái gì đó tương tự hay không.


1
@WmasterJ: Tôi thấy rằng Nhóm IE thực sự đã đề xuất điều này (hoặc thứ gì đó tương tự) được đưa vào tiêu chuẩn (hồi năm 2008): markmail.org/thread/ugzdcamtyftcyk6y .
Daniel Vassallo

45
Lần này IE đã đúng. Rõ ràng là điều này là cần thiết.
JeroenEijkhof

Tôi không hiểu điều này, Microsoft nói: "Thuộc tính localStorage cung cấp vùng lưu trữ liên tục cho các miền. Nó cho phép các ứng dụng Web lưu trữ gần 10 MB dữ liệu người dùng, chẳng hạn như toàn bộ tài liệu hoặc hộp thư của người dùng, trên máy khách vì lý do hiệu suất. " nhưng ở cuối còn lại thì không gian trả về 5000000 (?!?!) tại sao ?!
Rui Lima,

3
@RuiLima, lưu ý rằng vì các ký tự trong javascript sử dụng hai byte thay vì một, 5000000 ký tự thực sự chiếm 10 MB dung lượng. Có vẻ như IE có thể đang báo cáo các ký tự còn lại, thay vì byte hoặc họ đã thay đổi ý định về giới hạn lưu trữ.
Ishmael Smyrnow

1
Thuộc tính còn lại không gian này rất quan trọng nếu bạn đang mong đợi việc tràn localStorage của mình tạo ra một ngoại lệ: IE sẽ không ném một ngoại lệ. Vì vậy, bạn cần phải kiểm tra thuộc tính này trước và sau khi cố gắng lưu vào localStorage. Nếu kích thước không thay đổi, bạn biết rằng bạn đã vượt quá giới hạn của mình.
Andy

15

Bạn có thể sử dụng dòng dưới đây để tính toán chính xác giá trị này và đây là jsfiddle để minh họa việc sử dụng nó

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

Tôi đang sử dụng thuật toán này để xác định không gian đã sử dụng cho tiện ích mở rộng chrome, nhưng tôi nhớ đã đọc một câu hỏi SO khác (quên câu hỏi nào, bây giờ) mà JS sử dụng chuỗi UTF-16 thay vì UTF-8 và như vậy, bạn phải tăng gấp đôi số byte bạn nhận được bằng cách thực hiện string.length. Không biết có đúng như vậy không? Nếu vậy, tôi sẽ phải cập nhật mã của tôi ...
Adam Tuttle

1
jsfiddle của bạn không tải trong trình duyệt của tôi (mac / chrome).
Justin

Có vẻ như bạn đã phá vỡ JSFiddle, mặc dù bạn vẫn có thể thấy đầu ra ở đây !
c24w

Bạn không phải nhân 8 với 8 byte cho mỗi ký tự hay tương tự như vậy?
George Mauer

George, ví dụ đó giả định bộ ký tự UTF-8 như được xác định bởi thẻ meta 'Loại nội dung' trên phần lớn các trang web HTML của Hoa Kỳ. Nếu bạn muốn tài khoản cho hỗ trợ unicode, hãy xem tại đây mathiasbynens.be/notes/javascript-unicode Hoặc để khắc phục nhanh, đây là một chức năng để tính hỗ trợ unicode trong JS github.com/craniumslows/Countable/commit/…
jas -

9

Chạy vào điều này ngày hôm nay trong khi thử nghiệm (vượt quá hạn ngạch bộ nhớ) và đưa ra giải pháp. IMO, biết giới hạn là gì và chúng ta đang ở đâu trong mối quan hệ ít có giá trị hơn nhiều so với việc thực hiện một cách chức năng để tiếp tục lưu trữ vượt quá hạn ngạch.

Do đó, thay vì cố gắng so sánh kích thước và kiểm tra dung lượng, hãy phản ứng khi chúng ta đã đạt đến hạn ngạch, giảm bộ nhớ hiện tại của chúng ta xuống một phần ba và tiếp tục lưu trữ. Nếu quá trình giảm đã nói không thành công, hãy ngừng lưu trữ.

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

Hàm này nằm trong một đối tượng wrapper, vì vậy public.set chỉ cần gọi chính nó. Bây giờ chúng tôi có thể thêm vào bộ nhớ và không phải lo lắng về hạn ngạch là bao nhiêu hoặc chúng tôi đã quá gần đến mức nào. Nếu một cửa hàng duy nhất vượt quá 1/3 kích thước hạn ngạch thì chức năng này sẽ ngừng tuyển chọn và ngừng lưu trữ, và tại thời điểm đó, bạn không nên lưu vào bộ nhớ đệm nữa, phải không?


5

Để thêm vào kết quả kiểm tra trình duyệt:

Firefox i = 22.

Phiên bản Safari 5.0.4 trên máy Mac của tôi không bị treo. Lỗi là Chrome. i = 21.

Opera Cho người dùng biết rằng trang web muốn lưu trữ dữ liệu nhưng không có đủ dung lượng. Người dùng có thể từ chối yêu cầu, tăng giới hạn số tiền được yêu cầu hoặc đến một số giới hạn khác hoặc đặt nó thành không giới hạn. Vào opera: webstorage để cho biết thông báo này có xuất hiện hay không. i = 20. Lỗi được tạo ra cũng giống như Chrome.

Chế độ tiêu chuẩn IE9 Lỗi như Chrome. i = 22.

IE9 ở chế độ tiêu chuẩn IE8 Thông báo trên bảng điều khiển "Lỗi: Không có đủ bộ nhớ để hoàn thành thao tác này". i = 22

IE9 trong chế độ cũ hơn lỗi đối tượng. i = 22.

IE8 Không có bản sao để kiểm tra, nhưng bộ nhớ cục bộ được hỗ trợ (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)

IE7 trở xuống Không hỗ trợ bộ nhớ cục bộ.


3

Bạn có thể kiểm tra trình duyệt của mình bằng kiểm tra hỗ trợ lưu trữ web này

Tôi đã thử nghiệm Firefox trên cả máy tính bảng Android và máy tính xách tay windows và Chromium chỉ trên windows kết quả:

  1. Firefox (cửa sổ):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : * không được hỗ trợ
  2. Firefox (android):

    • localStorage : 2560k char
    • sessionStorage : Không giới hạn (chạy thử nghiệm chính xác lên đến 10240k char == 20480k byte)
    • localStorage : không được hỗ trợ
  3. Chromium (cửa sổ):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : không được hỗ trợ

Cập nhật

Trên phiên bản Google Chrome 52.0.2743.116 m (64-bit) giới hạn trong đó 5101kký tự thấp hơn một chút . Điều này có nghĩa là tối đa có sẵn có thể thay đổi trong các phiên bản.


Bạn brobably nghĩa 5120 k char
Juribiyan

@Juribiyan Vâng, tôi có.
Morteza Tourani

2

Ước gì tôi có thể thêm điều này trong một bình luận - không đủ đại diện, xin lỗi.

Tôi đã chạy một số bài kiểm tra hiệu suất - mong đợi JSON.stringify (localStorage) .length sẽ là một lựa chọn đắt tiền với tỷ lệ chiếm dụng localStorage lớn.

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

Nó thực sự là như vậy - đắt hơn khoảng 50 lần so với việc theo dõi những gì bạn đang lưu trữ và tệ hơn là localStorage đầy đủ hơn.


2

Chức năng này nhận được bộ nhớ chính xác có sẵn / còn lại:

Tôi đã tạo một bộ các chức năng hữu ích cho localStorage * tại đây *

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

Lưu ý, cách này không nhanh lắm, vì vậy đừng sử dụng nó mọi lúc.

Với điều này, tôi cũng phát hiện ra rằng: Tên-Vật phẩm sẽ chiếm nhiều không gian bằng chiều dài của nó, Giá-trị Vật phẩm cũng sẽ chiếm nhiều không gian bằng chiều dài của chúng.

Bộ nhớ tối đa tôi nhận được - tất cả khoảng 5M:

  • 5000000 ký tự - Cạnh
  • 5242880 ký tự - Chrome
  • 5242880 ký tự - Firefox
  • 5000000 ký tự - IE

Bạn sẽ tìm thấy một số mã được chú thích trong trò chơi để xem tiến trình trong bảng điều khiển.

Đã cho tôi chút thời gian để làm, hy vọng điều này sẽ giúp ích ☺


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

Tôi cần thực sự mô phỏng và kiểm tra xem mô-đun của mình sẽ làm gì khi bộ nhớ đầy, vì vậy tôi cần có độ chính xác chặt chẽ về thời điểm bộ nhớ đầy, thay vì câu trả lời được chấp nhận, điều này làm mất độ chính xác đó với tốc độ i ^ 2.

Đây là tập lệnh của tôi, luôn tạo ra độ chính xác là 10 khi đạt đến giới hạn bộ nhớ và khá nhanh chóng mặc dù có một số tối ưu hóa dễ dàng ... CHỈNH SỬA: Tôi đã làm cho tập lệnh tốt hơn và với độ chính xác chính xác:

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

Điều này có thể giúp ai đó. Trong chrome, có thể yêu cầu người dùng cho phép sử dụng thêm dung lượng đĩa nếu cần:

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

Truy cập https://developers.google.com/chrome/whitepapers/storage#asking_more để biết thêm thông tin.

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.