Thank you for a great library :)
I could not find a sample in the Dexie docs so I thought I might ask for possible support of binary data/blobs in Dexie.js.
https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
Are there any approaches today?
Thanks.
No, there's no code to specifically make binary blobs work but it is probably a common requirement so pull request would be more than welcome.
If someone would start fixing this, please give a note at this issue that is is in progress. Otherwise, I'll try to address it later on. Also, it would be great to begin with a unit test in for example test/tests-table.js to check if a fix is needed or if it works out-of-the box as is.
It does not work out of the box. I get the following error:
DOMException [DataError: "Data provided to an operation does not meet requirements."
code: 0
nsresult: 0x80660005
(This was in Firefox where it should have worked if it was going to work anywhere.) I can provide a short example but I am not very familiar with github and don't know what the appropriate way to do that is.
Thanks for testing this out. You could just paste a piece of code in this issue and I could insert it in a unit test and try finding a solution to solve it.
Here's my example. Most of this I borrowed from one place or another but it does retrieve an image from my website successfully and display it, it just can't add it to the database. It could be my error, though. For now I'm using localStorage for the images I need, but many thanks for sparing me the horrors of raw IndexedDB. Sorry about the formatting :(
(!DOCTYPE html)
(html)
(head)
(title)Blob Test(/title)
(script src="Dexie.min.js")(/script)
(script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js")(/script>
(script src="test.js">(/script)
(/head)
(body)
(img id="testimg" src="")
(script src="testmain.js")(/script)
(/body)
(/html)
$(function() {
var patno = 1;
var pid = "ARM001";
var db = new Dexie("testdb");
db.version(1).stores({ // this defines the keys of the stores
thumbs: 'patno'
});
Thumbs = db.thumbs.defineClass({
patno: Number,
thumb: Object
});
Thumbs.prototype.save = function() {
return db.thumbs.put(this);
};
db.on('error', function (err) {
// Catch all uncaught DB-related errors and exceptions
console.error(err);
});
db.open()
.catch(function(error){
console.log('Error: ' + error);
});
var xhr = new XMLHttpRequest(), blob, fileReader = new FileReader();
url = "../graphics/pat/" + pid.substr(0, 1) + "/" + pid + "_1.jpg";
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// Create a blob from the response
blob = new Blob([xhr.response], {type: "image/jpeg"});
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
$("#testimg").attr("src", result);
// Store Data URL
db.thumbs.put(result, patno);
};
// Load blob as Data URL
fileReader.readAsDataURL(blob);
}
}, false);
// Send XHR
xhr.send();
});
ArrayBuffers, which are binary data, works great on IE,Edge,Chrome, Opera and Firefox:
https://jsfiddle.net/dfahlander/kgsbbhca/
Tried with an Uint8Array as well and it worked great too.
I was storing images in IndexedDB using Dexie with great success. For reading these images I was using https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
I was using this code for defineClass of files in my app:
var FileObject = table.defineClass({
Data: Blob,
Date: String,
FileId: Number,
FileName: String,
FilePath: String,
Hash: String,
Type: String
});
FileObject.prototype.objectUrl = "";
FileObject.prototype.getObjectUrl = function () {
if (this.objectUrl !== "" && !this.disposed) {
return this.objectUrl;
} else if (!this.disposed) {
this.objectUrl = URL.createObjectURL(this.Data);
return this.objectUrl;
} else {
console.log('File disposed!');
throw "File disposed!";
}
};
FileObject.prototype.revokeObjectURL = function () {
URL.revokeObjectURL(this.objectUrl);
this.objectUrl = "";
};
FileObject.prototype.readAsText = function () {
var deferred = $q.defer();
var reader = self._getReader(deferred);
reader.readAsText(this.Data, 'windows-1252');
return deferred.promise;
};
FileObject.prototype.readAsArrayBuffer = function () {
var deferred = $q.defer();
var reader = self._getReader(deferred);
reader.readAsArrayBuffer(this.Data);
return deferred.promise;
};
FileObject.prototype.disposed = false;
FileObject.prototype.disposeData = function () {
URL.revokeObjectURL(this.objectUrl);
this.objectUrl = "";
this.Data = null;
this.disposed = true;
};
Cool! Thanks for that. The reason this issue is still open is because I actually haven't tested using blobs. And I've heard that there might be bugs in various browsers when storing blobs in indexedDB. So if there's an issue with it, it's probably just on certain browsers.
When there's time, i'd love to add a unit test for blobs in the test suite. Pull requests for this is also welcome. I'll keep the issue open until done.
Blob testing now part of the unit test suite in master (version 2.0). It turned out that we already had blob support if no hooks were involved.
The commit that fixes this is https://github.com/dfahlander/Dexie.js/commit/75bbbb4605c2b30a23ac63a76fb4798233686add
Most helpful comment
I was storing images in IndexedDB using Dexie with great success. For reading these images I was using https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
I was using this code for defineClass of files in my app: