Reputation: 4326
I've been pulling my hair out for hours now with a question that has been asked a few times around here: I have binary data from a flash audio recorder, which I turn into a dataURL and then want to convert to a blob for upload. SO gave me several answers, which are all essentially the same:
I wrote the following code based on the above
var data = window.atob(dataURL.split(',')[1]);
var length = data.length;
var uInt8Array = new Uint8Array(length);
for (var i = 0; i < length; ++i) {
uInt8Array[i] = data.charCodeAt(i);
}
var myfile = new Blob([uInt8Array], {'type': 'audio/x-wav'});
This works perfectly in firefox nightly (20) and chrome 25, but chromium 20 keeps telling me the size of myfile is 19 bytes (when it should be several kb), and subsequent upload fails consistently. Is this a bug in chromium, or did I miss a doc saying it is not supported yet? Any alternative ideas?
Upvotes: 1
Views: 1607
Reputation: 25381
Use my code convert dataURI to blob.
function dataURLtoBlob(dataURL) {
var arr = dataURL.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
Upvotes: 1
Reputation: 4326
It looks like there's a bug in chromium's Blob()
constructor when called with certain parameters.
I narrowed down the issue on jsfiddle (run in chromium to see the issue, other browsers seem to handle it properly, both blob sizes should be 32)
Here's the code I put together to get around it:
var data = window.atob(dataURL.split(',')[1]);
var length = data.length;
var buffer = new ArrayBuffer(length); // added this line
var uInt8Array = new Uint8Array(buffer);
for (var i = 0; i < length; ++i) {
uInt8Array[i] = data.charCodeAt(i);
}
// two options here:
// buggy: produces a 19byte long file in chromium
var myfile = new Blob([uInt8Array], {'type': 'audio/x-wav'});
// works in chromium (and firefox), but produces a deprecation warning in chrome
var myfile = new Blob([buffer], {'type': 'audio/x-wav'});
I ended up running the first alternative, then if (myfile.size == 19) {
to get the second one if needed
Upvotes: 1