HM2K
HM2K

Reputation: 1511

Is there a way to increase the size of localStorage in Google Chrome to avoid QUOTA_EXCEEDED_ERR: DOM Exception 22

I've written a webapp that allows you to store the images in the localStorage until you hit save (so it works offline, if signal is poor).

When the localStorage reaches 5MB Google Chrome produces an error in the javascript console log:

Uncaught Error: QUOTA_EXCEEDED_ERR: DOM Exception 22

How do I increase the size of the localStorage quota on Google Chrome?

Upvotes: 40

Views: 80132

Answers (7)

Donovan P
Donovan P

Reputation: 641

I have also encountered the same issue. After careful consideration, I believe that migrating from localStorage to other types of local storage, such as indexedDB, is a better approach when dealing with large amounts of data.

The reason is that localStorage operates on blocking synchronous processes. Storing a significant amount of data using synchronous processes is generally not recommended (which is likely why the Chrome developer team is adamant about not allowing users or developers to increase the 5MB hard limit of localStorage).

However, let's be honest... we appreciate the simplicity, ease of use, and straightforwardness of the localStorage API. It is unlike indexedDB in those aspects.

Therefore, I recommend using an alternative library: https://github.com/dreamsavior/Better-localStorage

This library is designed to be similar to localStorage, making the migration process easy:

const MyLocalStorage = require('better-localstorage');
await myStorage.setItem("someKey", { "someObject": "with the value" });
const value = await myStorage.getItem("someKey");
console.log(value);

Note that you don't need to convert the JavaScript object into JSON.

Using the native API, you would need to do the following:

myStorage.setItem("someKey", JSON.stringify({ "someObject": "with the value" }));
const value = JSON.parse(myStorage.getItem("someKey"));
console.log(value);

Upvotes: 0

Youth overturn
Youth overturn

Reputation: 417

https://stackoverflow.com/a/5664344/2630686 The above answer is much amazing. I applied it in my project and implement a full solution to request all kinds of resource.

// Firstly reference the above ldb code in the answer I mentioned.
export function get_file({ url, d3, name, enable_request = false }) {
  if (name === undefined) { // set saved data name by url parsing alternatively
    name = url.split('?')[0].split('/').at(-1).split('.')[0];
  }
  const html_name = location.href.split('/').at(-1).split('.')[0]
  name = `${html_name}_${name}`
  let ret = null;
  const is_outer = is_outer_net(url); // check outer net url by its start with http or //
  // try to access data from local. Return null if not found
  if (is_outer && !enable_request) {
    if (localStorage[name]) {
      ret = new Promise(resolve => resolve(JSON.parse(localStorage[name])));
    } else {
      ret = new Promise(r => {
        ldb.get(name, function (value) {
          r(value)
        })
      });
    }
  } else {
    ret = new Promise(r => r(null))
  }
  ret.then(data => {
    if (data) {
      return data
    } else {
      const method = url.split('.').at(-1)
      // d3 method supported
      if (d3 && d3[method]) {
        ret = d3[method](url)
      } else {
        if (url.startsWith('~/')) { // local files accessed supported. You need a local service that can return local file data by requested url's address value
          url = `http://localhost:8010/get_file?address=${url}`
        }
        ret = fetch(url).then(data => {
          // parse data by requested data type
          if (url.endsWith('txt')) {
            return data.text()
          } else {

            return data.json()
          }
        })
      }
      ret = ret.then(da => {
        data = da
        if (is_outer) { // save data to localStorage firstly
          localStorage[name] = JSON.stringify(data);
        }
      }).catch(e => { // save to ldb if 5MB exceed
        ldb.set(name, data);
      }).finally(_ => {

        return data;
      });
    }
  })
  return ret;
}

Upvotes: 1

Here you can test your program , you should handle also the cases when the cuota is exceed enter image description here

Upvotes: 2

Pawel
Pawel

Reputation: 18222

5MB is a hard limit and that is stupid. IndexedDB gives you ~50MB which is more reasonable. To make it easier to use try Dexie.js https://github.com/dfahlander/Dexie.js

Update:

Dexie.js was actually still an overkill for my simple key-value purposes so I wrote this much simpler script https://github.com/DVLP/localStorageDB

with this you have 50MB and can get and set values like that

// Setting values
ldb.set('nameGoesHere', 'value goes here');

// Getting values - callback is required because the data is being retrieved asynchronously:
ldb.get('nameGoesHere', function (value) {
  console.log('And the value is', value);
});

Copy/paste the line below so ldb.set() and ldb.get() from the example above will become available.

!function(){function e(t,o){return n?void(n.transaction("s").objectStore("s").get(t).onsuccess=function(e){var t=e.target.result&&e.target.result.v||null;o(t)}):void setTimeout(function(){e(t,o)},100)}var t=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;if(!t)return void console.error("indexDB not supported");var n,o={k:"",v:""},r=t.open("d2",1);r.onsuccess=function(e){n=this.result},r.onerror=function(e){console.error("indexedDB request error"),console.log(e)},r.onupgradeneeded=function(e){n=null;var t=e.target.result.createObjectStore("s",{keyPath:"k"});t.transaction.oncomplete=function(e){n=e.target.db}},window.ldb={get:e,set:function(e,t){o.k=e,o.v=t,n.transaction("s","readwrite").objectStore("s").put(o)}}}();

Upvotes: 29

Liza Daly
Liza Daly

Reputation: 2963

You can't, it's hard-wired at 5MB. This is a design decision by the Chrome developers.

In Chrome, the Web SQL db and cache manifest also have low limits by default, but if you package the app for the Chrome App Store you can increase them.

See also Managing HTML5 Offline Storage - Google Chrome.

Upvotes: 18

Florian Rotagnon
Florian Rotagnon

Reputation: 91

You can't but if you save JSON in your localStorage you can use a library to compress data like : https://github.com/k-yak/JJLC

demo : http://k-yak.github.io/JJLC/

Upvotes: 3

Ben
Ben

Reputation: 35613

The quota is for the user to set, how much space he wishes to allow to each website.

Therefore since the purpose is to restrict the web pages, the web pages cannot change the restriction.

If storage is low, you can prompt the user to increase local storage.

To find out if storage is low, you could probe the local storage size by saving an object then deleting it.

Upvotes: 1

Related Questions