Skip to content

Instantly share code, notes, and snippets.

@robnyman
Created February 23, 2012 17:55
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save robnyman/1894032 to your computer and use it in GitHub Desktop.
Save robnyman/1894032 to your computer and use it in GitHub Desktop.
IndexedDB storing and retrieving files
(function () {
// IndexedDB
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB,
IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction,
dbVersion = 1.0;
// Create/open database
var request = indexedDB.open("elephantFiles", dbVersion),
db,
createObjectStore = function (dataBase) {
// Create an objectStore
console.log("Creating objectStore")
dataBase.createObjectStore("elephants");
},
getImageFile = function () {
// Create XHR
var xhr = new XMLHttpRequest(),
blob;
xhr.open("GET", "elephant.png", true);
// Set the responseType to blob
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
console.log("Image retrieved");
// Blob as response
blob = xhr.response;
console.log("Blob:" + blob);
// Put the received blob into IndexedDB
putElephantInDb(blob);
}
}, false);
// Send XHR
xhr.send();
},
putElephantInDb = function (blob) {
console.log("Putting elephants in IndexedDB");
// Open a transaction to the database
var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE);
// Put the blob into the dabase
var put = transaction.objectStore("elephants").put(blob, "image");
// Retrieve the file that was just stored
transaction.objectStore("elephants").get("image").onsuccess = function (event) {
var imgFile = event.target.result;
console.log("Got elephant!" + imgFile);
// Get window.URL object
var URL = window.URL || window.webkitURL;
// Create and revoke ObjectURL
var imgURL = URL.createObjectURL(imgFile);
// Set img src to ObjectURL
var imgElephant = document.getElementById("elephant");
imgElephant.setAttribute("src", imgURL);
// Revoking ObjectURL
URL.revokeObjectURL(imgURL);
};
};
request.onerror = function (event) {
console.log("Error creating/accessing IndexedDB database");
};
request.onsuccess = function (event) {
console.log("Success creating/accessing IndexedDB database");
db = request.result;
db.onerror = function (event) {
console.log("Error creating/accessing IndexedDB database");
};
// Interim solution for Google Chrome to create an objectStore. Will be deprecated
if (db.setVersion) {
if (db.version != dbVersion) {
var setVersion = db.setVersion(dbVersion);
setVersion.onsuccess = function () {
createObjectStore(db);
getImageFile();
};
}
else {
getImageFile();
}
}
else {
getImageFile();
}
}
// For future use. Currently only in latest Firefox versions
request.onupgradeneeded = function (event) {
createObjectStore(event.target.result);
};
})();
@vincentmac
Copy link

I had some trouble getting this to work in Chrome (a chrome app to be more specific). I was running into an issue with indexedDB not accepting Blobs. My workaround involved using the FileReader API to convert the blob to an ArrayBuffer and then storing that new array buffer in indexedDB.

    function saveAsset(blob) {
        var reader = new FileReader();

        // Create a new blob from the xhr.response blob (which has a type of `text/plain`)
        var file = new Blob([blob], {type:'image'});

        var item = {
            url: that.model.get('thumbnail_url'),
            md5: that.model.get('md5hash'),
            expiration: that.model.get('expiration')
        };

        reader.onload = function(e) {
            item.file = e.target.result;  // ArrayBuffer representation of the image

            // Business logic to store data in indexedDB
            // This is for my use case. Your own use case may look like the above gist
            that.offlineAssets.put(item.url, item, function success(result) {
                callback();
            });
        }

        // Convert Blob image to ArrayBuffer before saving in indexedDB.
        reader.readAsArrayBuffer(blob);
    }

Then after retrieving your object from indexedDB convert it to a blob:

var blob = new Blob([asset.file], {type: 'image'});

Note: In my use case I am storing additional data in my idb object and have the ArrayBuffer at asset.file.

Then continue with creating the objectURL as outlined in the gist.

@cauerego
Copy link

There should be no need for all that. Something basically like this should work:

var transaction = db.transaction([objectstore], "readonly");
var objectStore = transaction.objectStore(objectstore);

var getAll = [];
objectStore.openCursor().onsuccess = function(evt) {
  var cursor = event.target.result;
  if (cursor) {
    getAll.push(cursor.value);
    cursor.continue();
  }
  else {
    var blobGetAll = JSON.stringify(getAll); // be aware this might hung and crash
    var url = window.URL.createObjectURL(
      new Blob(blobGetAll, {'type': 'application/octet-stream'})
    );
    link.attr('href', url);
    link.trigger('click');
  }
};

@jimmywarting
Copy link

This would have been better without the "image" parts

@atb00ker
Copy link

At line 74; I am able to read the value of response inside request.onsuccess function, how do i store the value in a variable and use it outside that function?

@xoneill
Copy link

xoneill commented Oct 26, 2018

It doesn't work on iOS 12. I am getting an error while attempting to write the image to indexeddb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment