Расчет использования пространства localStorage
Я создаю приложение, используя редактор Bespin и localStorage HTML5. Он хранит все файлы локально и помогает с грамматикой, использует JSLint и некоторые другие парсеры для CSS и HTML, чтобы помочь пользователю.
Я хочу подсчитать, сколько лимита localStorage было использовано и сколько там на самом деле. Возможно ли это сегодня? Я думал, чтобы не просто вычислить биты, которые хранятся. Но опять же, я не уверен, что еще я не могу измерить.
13 ответов
Я не нашел универсального способа получить оставшееся ограничение для нужных мне браузеров, но я обнаружил, что, когда вы достигаете предела, появляется сообщение об ошибке. Это, конечно, отличается в каждом браузере.
Чтобы добиться максимума, я использовал этот маленький скрипт:
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");
От этого я получил эту информацию:
Гугл Хром
- DOMException:
- код: 22
- сообщение: "Не удалось выполнить setItem для хранилища: установка значения" data "превысила квоту".
- имя: "QuotaExceededError"
Mozilla Firefox
- DOMException:
- код: 1014
- сообщение: "Максимальный размер постоянного хранилища достигнут"
- имя: "NS_ERROR_DOM_QUOTA_REACHED"
Сафари
- DOMException:
- код: 22
- сообщение: "QuotaExceededError: DOM Exception 22"
- имя: "QuotaExceededError"
Internet Explorer, Edge (сообщество)
- DOMException:
- код: 22
- сообщение: "QuotaExceededError"
- имя: "QuotaExceededError"
Мое решение
Пока что мое решение состоит в том, чтобы добавить дополнительный вызов каждый раз, когда пользователь будет сохранять что-либо. И если будет обнаружено исключение, я скажу им, что у них заканчивается емкость.
Редактировать: Удалить добавленные данные
Я забыл упомянуть, что для того, чтобы это на самом деле работало, вам нужно будет удалить DATA
предмет, который был установлен изначально. Изменение отражено выше с помощью функции removeItem().
Вы можете получить приблизительную идею, используя методы JSON, чтобы превратить весь объект localStorage в строку JSON:
JSON.stringify(localStorage).length
Я не знаю, насколько точной была бы байта, особенно с несколькими байтами добавленной разметки, если вы используете дополнительные объекты - но я думаю, что это лучше, чем думать, что вы нажимаете только 28 КБ и вместо этого делаете 280 КБ (или наоборот). Versa).
IE8 реализует remainingSpace
Свойство для этой цели:
alert(window.localStorage.remainingSpace); // should return 5000000 when empty
К сожалению, кажется, что это не доступно в других браузерах. Однако я не уверен, что они реализуют нечто подобное.
Вы можете использовать строку ниже, чтобы точно рассчитать это значение, и вот jsfiddle для иллюстрации его использования
alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
Наткнулся на это сегодня во время тестирования (превышение квоты хранилища) и выбрал решение. ИМО, знание того, что такое предел и где мы находимся в отношениях, гораздо менее ценно, чем реализация функционального способа продолжения хранения за пределами квоты.
Таким образом, вместо того, чтобы пытаться сравнивать размеры и проверять емкость, давайте отреагируем, когда мы достигнем квоты, уменьшим текущее хранилище на треть и возобновим хранение. Если указанное сокращение не удается, прекратите хранение.
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, размер квоты - это место, где эта функция прекращает отбраковку и прекращает хранение, и в этот момент вам все равно не следует кэшировать, верно?
Чтобы добавить в браузер результаты теста:
Firefox я =22.
Safari версии 5.0.4 на моем Mac не зависал. Ошибка как Chrome. I =21.
Opera Сообщает пользователю, что веб-сайт хочет хранить данные, но ему не хватает места. Пользователь может отклонить запрос, увеличить лимит до требуемой суммы или до нескольких других лимитов или установить его как неограниченный. Перейти к опере: интернет-хранилище, чтобы сказать, появляется ли это сообщение или нет. I =20. Выдается ошибка такая же, как Chrome.
Стандартный режим IE9 Ошибка как Chrome. I =22.
IE9 в стандартном режиме IE8. Сообщение консоли: "Ошибка: недостаточно памяти для выполнения этой операции". I =22
IE9 в старых режимах объекта ошибка. I =22.
IE8 У вас нет копии для тестирования, но поддерживается локальное хранилище (http://stackru.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)
IE7 и ниже Не поддерживает локальное хранилище.
Вы можете протестировать свой браузер с помощью этого теста поддержки веб-хранилища.
Я тестировал Firefox как на своем планшете с Android, так и на ноутбуке с Windows, а Chromium только на Windows:
Firefox(окна):
- localStorage: 5120 тыс. символов
- sessionStorage: 5120 Кб
- localStorage: * не поддерживается
Firefox(андроид):
- localStorage: 2560 тыс. символов
- sessionStorage: неограниченно (в точности тест занимает до 10240 тыс. символов == 20480 тыс. байт)
- localStorage: не поддерживается
Хром(окна):
- localStorage: 5120 тыс. символов
- sessionStorage: 5120 Кб
- localStorage: не поддерживается
Обновить
В Google Chrome версии 52.0.2743.116 м (64-разрядная версия) ограничения, где немного ниже 5101k
персонажи. Это означает, что максимальный доступный может измениться в версии.
Хотел бы я добавить это в комментарии - не достаточно репутации, извините.
Я выполнил некоторые тесты производительности - ожидая, что JSON.stringify(localStorage).length будет дорогостоящим оператором при большой загрузке localStorage.
http://jsperf.com/occupied-localstorage-json-stringify-length
Это действительно так - примерно в 50 раз дороже, чем отслеживание того, что вы храните, и становится еще хуже, чем полнее становится localStorage.
Эта функция получает точное доступное хранилище / осталось:
Я сделал набор полезных функций для 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();
Обратите внимание, что это не очень быстро, поэтому не используйте его все время.
С этим я также узнал, что: Item-Name будет занимать столько же места, сколько его длина, Item-Value также будет занимать столько же места, сколько их длина.
Максимальное хранилище, которое я получил - всего около 5М:
- 5000000 символов - Edge
- 5242880 символов - хром
- 5242880 символов - Firefox
- 5000000 символов - IE
Вы найдете некоторый закомментированный код в скрипте, чтобы увидеть прогресс в консоли.
Заняло у меня некоторое время, надеюсь, это поможет ☺
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
}
Мне нужно было на самом деле смоделировать и протестировать, что будет делать мой модуль при заполнении хранилища, поэтому мне нужно было получить точную точность при заполнении хранилища, а не принятый ответ, который теряет эту точность со скоростью 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)
}
Этот скрипт вернет false, если локальное хранилище недоступно, или вернет точное доступное пространство в локальном хранилище с точностью до ближайшего символа, независимо от того, выдает ли браузер ошибку или просто ничего не добавляет в локальное хранилище, когда локальное хранилище заполнено.
var localstorageavail;
function localstoragetest(remaining) {
if (typeof(Storage) !== "undefined") {
localstorageavail = true;
var usedspace = JSON.stringify(localStorage).length;
if (remaining == true) {
var unusedspace = 0, data = "m", adddata, stored = 0;
for (adddata = "m";;) {
try {
localStorage.setItem("UN", data);
if (stored < JSON.stringify(localStorage).length) {
stored = JSON.stringify(localStorage).length;
adddata += adddata;
data += adddata;
}
else throw "toolong";
} catch(e) {
if (adddata == "m") break;
else adddata = "m";
data += adddata;
}
}
var totalspace = JSON.stringify(localStorage).length;
unusedspace = totalspace - usedspace;
localStorage.removeItem("UN");
alert("Space Used Calculated: " + usedspace + " " + "\nUnused space: " + unusedspace + "\nSpace Used according to browser: " + JSON.stringify(localStorage).length)
}
} else {
// alert("Sorry! No Web Storage support..");
localstorageavail = false;
}
if (localstorageavail == false) return localstorageavail;
else return unusedspace;
}
localstoragetest(true);
Это может помочь кому-то. В 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 для получения дополнительной информации.