Розрахунок використання місцевого сховища


80

Я створюю програму за допомогою редактора Bespin та localStorage HTML5. Він зберігає всі файли локально та допомагає в граматиці, використовує JSLint та деякі інші парсери для CSS та HTML, щоб допомогти користувачеві.

Я хочу підрахувати, яка частина обмеження localStorage була використана і скільки насправді існує. Чи можливо це сьогодні? Я думав про те, щоб не просто обчислити біти, які зберігаються. Але знову ж таки я не впевнений, що є ще того, що я не можу виміряти.



JavaScript / HTML5 LocalStorage корисно Функції: stackoverflow.com/q/34245593/4339170
CoderPi

Можливий дублікат How to find the size of localStorage
tripleee

Відповіді:


73

Ви можете отримати приблизну ідею за допомогою методів JSON, щоб перетворити весь об’єкт localStorage на рядок JSON:

JSON.stringify(localStorage).length

Я не знаю, наскільки це було б байтово точно, особливо з кількома байтами доданої розмітки, якщо ви використовуєте додаткові об'єкти - але я вважаю, що це краще, ніж думати, що ви натискаєте лише 28 КБ, а замість цього робите 280 КБ (або віце- навпаки).


4
Це насправді досить точно для роботи. Коли localStorage максимально обмежений у Chrome 14, JSON.stringify (localStorage) .length === 2636625 або 2,51448 МБ, що досить близько ( dev-test.nemikor.com/web-storage/support-test ). Використовується в тандемі з спробою {} catch {}, і у вас вистачить для створення допоміжного класу.
Крістофер

13
зауважте, що, як зазначено у тесті, який ви посилаєте, це розмір у символах, а не в байтах: "Рядки в JavaScript - це UTF-16, тому кожен символ вимагає двох байт пам'яті. Це означає, що, хоча багато браузерів мають 5 Обмеження в МБ, ви можете зберігати лише 2,5 млн символів. "
Мортімер,

52

Я не знайшов універсального способу отримати решту обмежень для потрібних браузерів, але виявив, що коли ви досягнете межі, з’являється повідомлення про помилку. Звичайно, це різниться в кожному браузері.

Щоб максимізувати це, я використав цей маленький скрипт:

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

Звідси я отримав таку інформацію:

Гугл хром

  • Виняток DOME:
    • код: 22
    • повідомлення: "Не вдалося виконати 'setItem' на 'Storage': встановлення значення 'data' перевищило квоту."
    • name: "QuotaExceededError"

Mozilla Firefox

  • Виняток DOME:
    • код: 1014
    • повідомлення: "Досягнуто максимальний розмір постійного сховища"
    • ім'я: "NS_ERROR_DOM_QUOTA_REACHED"

Сафарі

  • Виняток DOME:
    • код: 22
    • повідомлення: "QuotaExceededError: DOM Exception 22"
    • name: "QuotaExceededError"

Internet Explorer, Edge (спільнота)

  • Виняток DOME:
    • код: 22
    • повідомлення: "QuotaExceededError"
    • name: "QuotaExceededError"

Моє рішення

Поки що моє рішення полягає в додаванні додаткового дзвінка кожного разу, коли користувач що-небудь збереже. І якщо буде вилучено виняток, я б сказав їм, що у них закінчується ємність для зберігання.


Редагувати: видалити додані дані

Я забув згадати, що для того, щоб це насправді працювало, вам потрібно буде видалити DATAелемент, який був встановлений спочатку. Зміна відображається вище за допомогою функції removeItem () .


Дуже приємно, чого було важливо, iколи цього було досягнуто в кожному випадку?
artlung

20-21 я думаю. Ви можете запустити тест самостійно, якщо хочете.
JeroenEijkhof

IE: ABORT_ERR: 20 код: 22 повідомлення: "QuotaExceededError" ім'я: "QuotaExceededError"
Руї Ліма

в IE ваш код викликає виняток перед закінченням простору: window.localStorage.remainingSpace: 805692 | window.localStorage.getItem ("ДАНІ"). довжина: 4194304 | JSON.stringify (localStorage) .length: 4194315 | i: 22
Руй Ліма

добре, тоді я можу обернути локальний код зберігання в блоці try catch і попередити користувача в блоці catch на розмір, що перевищує.
Нірус

26

IE8 реалізує remainingSpaceвластивість для цієї мети:

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

На жаль, здається, що це недоступно в інших браузерах. Однак я не впевнений, чи реалізують вони щось подібне.


1
@WmasterJ: Я бачу, що команда IE насправді запропонувала включити це (або щось подібне) до стандарту (ще в 2008 році): markmail.org/thread/ugzdcamtyftcyk6y .
Даніель Вассалло

45
Цього разу IE мав рацію. Здавалося б, очевидно, що це потрібно.
JeroenEijkhof

Я не розумію цього, Microsoft каже: "Атрибут localStorage забезпечує постійні області зберігання доменів. Він дозволяє веб-програмам зберігати на клієнті майже 10 МБ даних користувачів, таких як цілі документи або поштова скринька користувача, з міркувань продуктивності. " але в кінці preostaлий Space повертає 5000000 (?!?!) чому ?!
Rui Lima

3
@RuiLima, зауважте, що оскільки символи в javascript займають два байти замість одного, 5000000 символів фактично займають 10 МБ місця. Схоже, IE може повідомляти залишилися символи, а не байти, або вони передумали обмежувати обсяг пам’яті.
Ізмаїл Смирнов

1
Це властивість preostaлого Space є важливим, якщо ви очікуєте, що ваше переповнення localStorage видасть виняток: IE не видасть жодного. Таким чином, вам потрібно перевірити це властивість до та після спроби збереження в localStorage. Якщо розмір не змінився, ви знаєте, що перевищили ліміт.
Енді,

15

Ви можете використовувати рядок нижче, щоб точно розрахувати це значення, і ось jsfiddle для ілюстрації його використання

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

Я використовую цей алгоритм для визначення використовуваного місця для розширення chrome, але я пам’ятаю, як прочитав ще одне запитання SO (забудьте, яке саме, зараз), що JS використовує рядки UTF-16 замість UTF-8, і як такий, вам потрібно подвоїти кількість байтів, яку ви отримуєте, виконуючи string.length. Чи знаєте ви, чи це правда? Якщо так, мені доведеться оновити свій код ...
Адам Таттл

1
ваш jsfiddle не завантажується в моєму браузері (mac / chrome).
Джастін

Схоже, ви зламали JSFiddle, хоча ви все ще можете побачити результати тут !
c24w

Вам не потрібно множити на 8 на 8 байт на символ або щось подібне?
Джордж Мауер,

Джордж, цей приклад передбачає набір символів UTF-8, як визначено мета-тегом "Content-Type" на більшості веб-сайтів HTML на базі США. Якщо ви хочете , щоб рахунок для підтримки юникода подивися тут mathiasbynens.be/notes/javascript-unicode Або для швидкого вирішення тут є функцією на рахунок підтримки Юнікоду в JS github.com/craniumslows/Countable/commit / ...
Иак -

9

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

Таким чином, замість того, щоб робити порівняння розмірів та перевірку ємності, давайте реагувати, коли ми досягнемо квоти, зменшити наш поточний обсяг пам’яті на третину та відновити зберігання. Якщо зазначене зменшення не вдається, припиніть зберігання.

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

Щоб додати до результатів тестування браузера:

Firefox i = 22.

Версія Safari 5.0.4 на моєму Mac не зависла. Помилка як Chrome. i = 21.

Opera повідомляє користувачеві, що веб-сайт хоче зберігати дані, але не має достатньо місця. Користувач може відхилити запит, збільшити ліміт до необхідної суми або до кількох інших обмежень, або встановити його як необмежений. Перейдіть до Opera: webstorage, щоб сказати, з’являється це повідомлення чи ні. i = 20. Виявлена ​​помилка така ж, як і Chrome.

Помилка стандартного режиму IE9 як Chrome. i = 22.

IE9 у режимі стандартних IE8 Повідомлення консолі "Помилка: Недостатньо місця для зберігання, щоб виконати цю операцію". i = 22

IE9 в попередніх режимах помилка об'єкта. i = 22.

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

IE7 і нижче Не підтримує локальне сховище.


3

Ви можете протестувати свій браузер за допомогою цього тесту підтримки веб-сховища

Я протестував Firefox як на планшеті Android, так і на ноутбуці Windows і на Chromium просто на результатах Windows:

  1. Firefox (вікна):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : * не підтримується
  2. Firefox (android):

    • localStorage : 2560k char
    • sessionStorage : необмежений (саме тестовий пробіг до 10240k char == 20480k байт)
    • localStorage : не підтримується
  3. Хром (вікна):

    • localStorage : 5120k char
    • sessionStorage : 5120k char
    • localStorage : не підтримується

Оновлення

У Google Chrome Версія 52.0.2743.116 м (64-розрядна) обмежує дещо нижчі 5101kсимволи. Це означає, що максимально доступний може змінюватися у версіях.


Ви brobably мав в виду 5120 K напівкоксу
Juribiyan

@Juribiyan Так.
Morteza Tourani

2

Хотілося б додати це в коментарі - недостатньо представників, вибачте.

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

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

Це справді так - приблизно в 50 разів дорожче, ніж відстежувати те, що ви зберігаєте, і погіршується, чим повніше отримує localStorage.


2

Ця функція отримує точне доступне / залишене сховище:

Я зробив набір корисних функцій для 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

У скрипці ви знайдете якийсь прокоментований код, щоб побачити прогрес у консолі.

На це мені зайняв трохи часу, сподіваюся, це допоможе ☺


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

Мені потрібно було насправді змоделювати та перевірити, що буде робити мій модуль, коли пам'ять заповнена, тому мені потрібно було отримати точну точність, коли пам'ять заповнена, а не прийняту відповідь, яка втрачає цю точність зі швидкістю 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)
}

0

Це може комусь допомогти. У chrome можна попросити користувача дозволити використовувати більше місця на диску, якщо це необхідно:

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

Відвідайте https://developers.google.com/chrome/whitepapers/storage#asking_more для отримання додаткової інформації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.