65

I have a DataURL from a canvas that shows my webcam. I turn this dataURL into a blob using Matt's answer from here: How to convert dataURL to file object in javascript?

How do I convert this blob back into the same DataURL? I've spent a day researching this and I'm astouned this isn't documented better, unless I'm blind.

EDIT: There is

var urlCreator = window.URL || window.webkitURL; 
var imageUrl = urlCreator.createObjectURL(blob); 

but it only returns a really short URL that seems to point at a local file, but I need to send the webcam data over a network.

Community
  • 1
  • 1
spacecoyote
  • 1,909
  • 3
  • 19
  • 24
  • 1
    Or if someone knows of any other two methods to convert between DataURL and Blob, I'd be extremely grateful. It's nagging me. – spacecoyote Apr 18 '14 at 08:49
  • 1
    Is it even possible to turn a URL into a blob, send the blob over a network and turn the blob into a URL again? Do I have a thinking mistake? – spacecoyote Apr 18 '14 at 09:32
  • 1
    Since my attempts at compressing the dataURL string and sending it that way seem to be failing too, I'll allow myself to bump this once more. – spacecoyote Apr 18 '14 at 12:33

5 Answers5

113

Use my code to convert between dataURL and blob object in javascript. (better than the code in your link.)

//**dataURL 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});
}

//**blob to dataURL**
function blobToDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {callback(e.target.result);}
    a.readAsDataURL(blob);
}

//test:
var blob = dataURLtoBlob('data:text/plain;base64,YWFhYWFhYQ==');
blobToDataURL(blob, function(dataurl){
    console.log(dataurl);
});
cuixiping
  • 24,167
  • 8
  • 82
  • 93
  • 4
    I think the thing that was not obvious to me about `FileReader ` is adding the `onload` event before you call `readAsDataURL` – Jazzy Jul 30 '17 at 22:53
14

Here is a Promise-based Typescript version with proper error checking.

function blobToDataURL(blob: Blob): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = _e => resolve(reader.result as string);
    reader.onerror = _e => reject(reader.error);
    reader.onabort = _e => reject(new Error("Read aborted"));
    reader.readAsDataURL(blob);
  });
}
Timmmm
  • 88,195
  • 71
  • 364
  • 509
5

Nevermind, it ended up working after sticking to the instructions in this thread Display image from blob using javascript and websockets and making my server forward raw (yet) unmodified BinaryWebSocketFrames.

Now I'm still fighting bad performance of the canvas (<1fp) but that might become subject of a new thread.

Community
  • 1
  • 1
spacecoyote
  • 1,909
  • 3
  • 19
  • 24
2

DataURL to Blob has a better solution:

const dataURL = "dataURL string...";
const res = await fetch(dataURL);
const blob = await res.blob();
Pinetree
  • 617
  • 4
  • 7
1

I like one-liners, so here's a Promise-based one to convert a blob to a data URL:

let blob = ...;
let dataUrl = await new Promise(r => {let a=new FileReader(); a.onload=r; a.readAsDataURL(blob)}).then(e => e.target.result);

Or, as a function:

function blobToDataUrl(blob) {
  return new Promise(r => {let a=new FileReader(); a.onload=r; a.readAsDataURL(blob)}).then(e => e.target.result);
}

let dataUrl = await blobToDataUrl(blob);
joe
  • 3,752
  • 1
  • 32
  • 41