Расчет использования пространства localStorage - PullRequest
74 голосов
/ 12 июня 2010

Я создаю приложение, используя редактор Bespin и HTML5 localStorage.Он хранит все файлы локально и помогает с грамматикой, использует JSLint и некоторые другие парсеры для CSS и HTML, чтобы помочь пользователю.

Я хочу подсчитать, сколько использовалось предела localStorage и сколько на самом деле, Возможно ли это сегодня? Я думал не просто вычислить биты, которые хранятся.Но опять же, я не уверен, что еще я не могу измерить.

Ответы [ 12 ]

67 голосов
/ 13 июня 2011

Вы можете получить приблизительную идею, используя методы JSON, чтобы превратить весь объект localStorage в строку JSON:

JSON.stringify(localStorage).length

Я не знаю, насколько это будет точно,особенно с несколькими байтами добавленной разметки, если вы используете дополнительные объекты - но я думаю, что это лучше, чем думать, что вы нажимаете только 28 КБ и вместо этого делаете 280 КБ (или наоборот).

47 голосов
/ 12 июня 2010

Я не нашел универсального способа получить оставшееся ограничение для нужных мне браузеров, но я обнаружил, что, когда вы достигаете предела, появляется сообщение об ошибке.Это, конечно, отличается в каждом браузере.

Чтобы максимально его использовать, я использовал этот маленький скрипт:

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

Из этого я получил эту информацию:

Google Chrome

  • DOMException:
    • код: 22 * ​​1015 *
    • сообщение: "Не удалось выполнить 'setItem' в 'Хранилище': установка значения«данные» превысили квоту. »
    • имя:« QuotaExceededError »

Mozilla Firefox

  • DOMException:
    • код: 1014
    • сообщение: «Достигнут максимальный размер постоянного хранилища»
    • имя: «NS_ERROR_DOM_QUOTA_REACHED»

Safari

  • DOMException:
    • код: 22 * ​​1047 *
    • сообщение: "QuotaExceededError: DOM Exception 22"
    • name: "QuotaExceededError"

Internet Explorer, Edge (сообщество)

  • DOMException:
    • код: 22 * ​​1063 *
    • сообщение: "QuotaExceededError "
    • имя:" QuotaExceededError "

Мое решение

Пока мое решениедобавить дополнительный вызов каждый раз, когда пользователь будет сохранять что-либо.И если возникнет исключение, я скажу им, что у них заканчивается емкость.


Редактировать: удалить добавленные данные

Я забылОтметим, что для того, чтобы это действительно работало, вам нужно удалить элемент DATA, который был установлен изначально.Изменение отражено выше с помощью функции removeItem () .

26 голосов
/ 12 июня 2010

IE8 реализует свойство remainingSpace для этой цели:

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

К сожалению, похоже, что это не доступно в других браузерах. Однако я не уверен, что они реализуют нечто подобное.

12 голосов
/ 13 апреля 2012

Вы можете использовать строку ниже, чтобы точно рассчитать это значение, а здесь - jsfiddle для иллюстрации его использования

alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
8 голосов
/ 27 сентября 2013

Натолкнулся на это сегодня во время тестирования (превышение квоты хранилища) и выбрал решение. ИМО, знание того, что такое предел и где мы находимся в отношениях, гораздо менее ценно, чем реализация функционального способа продолжения хранения за пределами квоты.

Таким образом, вместо того, чтобы пытаться сравнивать размеры и проверять емкость, давайте реагируем, когда мы достигаем квоты, сокращаем текущее хранилище на треть и возобновляем хранение. Если указанное сокращение не удалось, прекратите хранение.

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

Эта функция находится внутри объекта-оболочки, поэтому public.set просто вызывает себя. Теперь мы можем добавить в хранилище и не беспокоиться о том, что квота или насколько мы близки к ней. Если единичное хранилище превышает 1/3, размер квоты - это место, где эта функция прекращает отбраковку и прекращает хранение, и в этот момент вам все равно не следует кэшировать, верно?

5 голосов
/ 06 сентября 2011

Чтобы добавить в браузер результаты теста:

Firefox i = 22.

Safari Версия 5.0.4 на моем Mac didn 'т повеситьОшибка как Chrome.я = 21.

Опера Сообщает пользователю, что веб-сайт хочет хранить данные, но не имеет достаточно места.Пользователь может отклонить запрос, увеличить лимит до требуемой суммы или до нескольких других ограничений или установить его на неограниченный.Перейти к опере: веб-хранилище, чтобы сказать, появляется ли это сообщение или нет.I = 20.Выдается ошибка, аналогичная Chrome.

Стандартный режим IE9 Ошибка как Chrome.i = 22.

IE9 в стандартном режиме IE8 Консольное сообщение «Ошибка: недостаточно памяти для выполнения этой операции».i = 22 * ​​1021 *

IE9 в более старых режимах ошибка объекта.я = 22.

IE8 Нет копии для тестирования, но поддерживается локальное хранилище (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)

IE7 и ниже Неподдержка локального хранилища.

3 голосов
/ 15 октября 2014

Вы можете протестировать ваш браузер с помощью этого теста поддержки веб-хранилища

Я тестировал Firefox на планшете Android и ноутбуке с ОС Windows и Chromium Результаты только для Windows:

  1. Firefox (windows):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : * не поддерживается
  2. Firefox (android):

    • localStorage : 2560k char
    • sessionStorage : Не ограничено (в точности тест выполняет до 10240 тыс. Символов == 20480 тыс. Байт)
    • localStorage : не поддерживается
  3. Хром (windows):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : не поддерживается

Обновление

В Google Chrome версии 52.0.2743.116 м (64-разрядных) ограничения, где немного меньше 5101k символов.Это означает, что максимальный доступный может изменяться в версиях.

2 голосов
/ 16 сентября 2014

Хотелось бы добавить это в комментарии - недостаточно реп, извините.

Я провел несколько тестов перфоманса - ожидал, что JSON.stringify (localStorage) .length будет дорогостоящим операцией при большой загрузке localStorage.

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

Это действительно так - примерно в 50 раз дороже, чем отслеживание того, что вы храните, и хуже, чем полнее localStorage.

1 голос
/ 27 января 2016

Мне нужно было на самом деле смоделировать и протестировать, что будет делать мой модуль при заполнении хранилища, поэтому мне нужно было получить точную точность при заполнении хранилища, а не принятый ответ, который теряет эту точность со скоростью i. ^ 2.

Вот мой сценарий, который всегда должен давать точность 10 при достижении ограничения памяти и довольно быстро, несмотря на некоторые простые оптимизации ... РЕДАКТИРОВАТЬ: Я сделал сценарий лучше и с точной точностью:

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)
}
1 голос
/ 12 декабря 2015

Эта функция возвращает точное доступное хранилище / осталось:

Я сделал набор полезных функций для localStorage * здесь *

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

Обратите внимание, что это не очень быстро, поэтому не используйте его все время.

С этим я также узнал, что: Имя элемента будет занимать столько же места, сколько его длина, Значение элемента также будет занимать столько же места, сколько их длина.

Максимальный объем памяти, который я получил - всего около 5М:

  • 5000000 символов - Edge
  • 5242880 символов - хром
  • 5242880 символов - Firefox
  • 5000000 символов - IE

Вы найдете некоторый закомментированный код в скрипте, чтобы увидеть прогресс в консоли.

Заняло у меня некоторое время, надеюсь, это поможет 10

...