Storing images and files in IndexedDB

The other day we wrote about how to Save images and files in localStorage, and it was about being pragmatic with what we have available today. There are, however, a number of performance implications with localStorage – something that we will cover on this blog later – and the desired future approach is utilizing IndexedDB. Here I’ll walk you through how to store images and files in IndexedDB and then present them through an ObjectURL.

The general approach

First, let’s talk about the steps we will go through to create an IndexedDB data base, save the file into it and then read it out and present in the page:

Create or open a database.

Create an objectStore (if it doesn’t already exist)

Retrieve an image file as a blob

Initiate a database transaction

Save that blob into the database

Read out that saved file and create an ObjectURL from it and set it as the src of an image element in the page

Creating the code

Let’s break down all parts of the code that we need to do this:

Create or open a database.

// IndexedDB
window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB,
IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction,
dbVersion = 1;
/*
Note: The recommended way to do this is assigning it to window.indexedDB,
to avoid potential issues in the global scope when web browsers start
removing prefixes in their implementations.
You can assign it to a varible, like var indexedDB… but then you have
to make sure that the code is contained within a function.
*/
// Create/open database
var request = indexedDB.open("elephantFiles", dbVersion);

The intended way to use this is to have the onupgradeneeded event triggered when a database is created or gets a higher version number. This is currently only supported in Firefox, but will soon be in other web browsers. If the web browser doesn’t support this event, you can use the deprecated setVersion method and connect to its onsuccess event.

This code gets the contents of a file as a blob directly. Currently that’s only supported in Firefox.
Once you have received the entire file, you send the blob to the function to store it in the database.

Initiate a database transaction

// Open a transaction to the database
var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE);

To start writing something to the database, you need to initiate a transaction with an objectStore name and the type of action you want to do – in this case read and write.

Save that blob into the database

// Put the blob into the dabase
transaction.objectStore("elephants").put(blob, "image");

Once the transaction is in place, you get a reference to the desired objectStore and then put your blob into it and give it a key.

Read out that saved file and create an ObjectURL from it and set it as the src of an image element in the page

Use the same transaction to get the image file you just stored, and then create an objectURL and set it to the src of an image in the page.
This could just as well, for instance, have been a JavaScript file that you attached to a script element, and then it would parse the JavaScript.

Web browser support

Supported since long (a number of versions back) in Firefox and Google Chrome. Planned to be in IE10 and a future version of Opera. Unclear about Safari.

onupgradeneeded

Supported in latest Firefox. Planned to be in Google Chrome soon and hopefully IE10 and a future version of Opera. Unclear about Safari.

Storing files in IndexedDB

Supported in Firefox 11 and later. Planned to be supported in Google Chrome. Hopefully IE10 will support it. Unclear about Safari and Opera.

XMLHttpRequest Level 2

Supported in Firefox and Google Chrome since long, Safari 5+ and planned to be in IE10 and Opera 12.

responseType “blob”

Currently only supported in Firefox. Will soon be in Google Chrome and is planned to be in IE10 and Opera 12. Unclear about Safari.

Demo and code

I’ve put together a demo with IndexedDB and saving images and files in it where you can see it all in action. Make sure to use any Developer Tool to Inspect Element on the image to see the value of its src attribute. Also make sure to check the console.log messages to follow the actions.

Thanks for asking!
Sorry, I should have been more clear about that: when it comes to storing files specifically, it works in Firefox 11 and later – please try Firefox Beta or Firefox Aurora and latest Google Chrome.

I’ll update the blog post with that info.

I hope that IE10 will support storing files before it is officially released.

Hi Abral, I´ve seen your app eLibri, GREAT!, I´m trying to do something of the sort with a MS SQL server and in ASP, i´m getting it all right till the getting the Json file from the server and putting it into the IndexedDB database, could you explain how you do it and maybe give us a glance at the server file that delivers the Json file? (I know it is in PHP but it would help) Thank´s in advance.

I can tell you a bit about Opera:
IndexedDB: I don’t think it’ll hit 12, but we’re working on it.
XHR2 blob (and arraybuffer) is coming in Opera 12.
onupgradeneeded: Of course we’re implementing the newest spec.

Is there a way to download huge content (~1 GB in total) to a database where the database needs to be in a consistent state all the time (e.g. a graph)?
– Parsing the whole blob is impossible due to its size.
– Using a single transaction for all chunks isn’t possible either, since during the download we need to get back to the event loop, and therefore the transaction becomes inactive.
– Using temporary object stores in the *same* database would be possible, but doubles the space needed during download.

Hi Robert,
Thanks for sharing this example, I´m trying to get this to work but instead of a image I´m trying to retrieve a Json file from a web service and putting it to the IndexedDB objectStore.
It looks something like this: [{“field1″:”value1″},{“field2″:”value2″},{“field3″:”value3″},{“field4″:”value4″}]
but as I’m a newbie to JavaScript it’s beeing a nightmare…
do you think you can post a example in how to do it?
Thanks in advance.
Ruben.

but it's actually putting something like this: [object Object],[object Object],[object Object],[object Object]" to the objectStore…
I'm not sure if I have to use the eval() or even the loop, can you give me a hand please?

This works great for me in FF(19.02), but not in Chrome (25.0.1364.172 m) or IE (10.09.200…). The image src in the sample is pre set to “elephant.png”, so it gives the false impression that it works in those browsers as well, but I am getting an error: Uncaught Error: “DataCloneError: DOM IDBDatabase Exception 25″ on this line: var put = transaction.objectStore(“elephants”).put(blob, “image”);

About the Author

Technical Evangelist & Editor of Mozilla Hacks. Gives talks & blogs about HTML5, JavaScript & the Open Web. Robert is a strong believer in HTML5 and the Open Web and has been working since 1999 with Front End development for the web - in Sweden and in New York City.
He regularly also blogs at http://robertnyman.com and loves to travel and meet people.