10

There is the following code:

console.log(blob);
var reader = new window.FileReader();
reader.onloadend = function() {            
  console.log(reader.result);
};
reader.readAsDataURL(blob);

blob is 'blob:http://localhost:3000/e3c23a22-75b1-4b83-b39a-75104d1909b9' and I've got the following error:

TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.

How can I fix this error and convert Blob to Base64 encoded image? Thanks in advance!

malcoauri
  • 11,904
  • 28
  • 82
  • 137

5 Answers5

7

I know this is an old question, but I came across this problem lately and it took me a while to fix it. So I am going to answer the question in case anyone run into it again.

First, I think the naming of variable blob is very confusing. Blob URLs and Blob Object are different things. This answer does a very good job explaining what a Blob URL is. I think you should rename it as below.

var blobUrl = 'blob:http://localhost:3000/e3c2...'

Then, the function readAsDataURL of FileReader requires a Blob Object as its parameter. And what you give it is the variable blob, which is a Blob URL.

So what you need to do is:

  1. Recover the Blob Object that is used to create the Blob URL
  2. Use readAsDataURL to convert the recovered Blob Object to base64 url

Here is the code I find in this answer:

var blob = new Blob(["Hello, world!"], { type: 'text/plain' });
var blobUrl = URL.createObjectURL(blob);

var xhr = new XMLHttpRequest;
xhr.responseType = 'blob';

xhr.onload = function() {
   var recoveredBlob = xhr.response;

   var reader = new FileReader;

   reader.onload = function() {
     var blobAsDataUrl = reader.result;
     window.location = blobAsDataUrl;
   };

   reader.readAsDataURL(recoveredBlob);
};

xhr.open('GET', blobUrl);
xhr.send();
Sun Haoran
  • 516
  • 1
  • 5
  • 13
1

Simply just use fetch api:

const blob = await fetch(blobUrl).then(res => res.blob())
Endless
  • 34,080
  • 13
  • 108
  • 131
0

You need to pass in the whole file object from the uploader and not just the blob url. By the whole file object i mean the name, type, url, etc.

Basically if the uploader has a file in the array, i.e files[0], you would pass in readAsDataURL(files[0]).

miken32
  • 42,008
  • 16
  • 111
  • 154
fes
  • 2,465
  • 11
  • 40
  • 56
-1

Sun Haoran's answer was fantastic, lead me in the right direction to better understanding and worked like a charm.
Below I will share what I did in Angular 11, based off Sun Haoran's answer. What I needed to achieve was doing the operation within a promise and maintaining scope when completed for TypeScript:

private blobUrlToBase64(blobUrl: string): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    const xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';

    xhr.onload = function () {
      reader.readAsDataURL(xhr.response);
      reader.onloadend = function () { resolve(reader.result as string); }
      reader.onerror = function (ev) { reject(`Exception reading Blob > xhr.response: ${xhr.response}\nLast Progress Event: ${ev}`); };
    };
    xhr.onerror = function (ev) { reject(`Exception fetching Blob > BlobUrl: ${blobUrl}\nLast Progress Event: ${ev}`); };

    xhr.open('GET', blobUrl);
    xhr.send();
  });
}
KeaganFouche
  • 581
  • 5
  • 12
  • the answer to a javascript question should be answered with javascript... – Endless Jan 09 '22 at 16:58
  • Yes, you're right, and Sun Haoran's answer is working for javascript. However, as I stated in my answer "What I needed to achieve was doing the operation within a promise and maintaining scope when completed for TypeScript". I stated this for a reason, Endless. People of the internet will arrive at this question for both JS and TS, having both solutions available will hopefully be of use to them. But strictly speaking, you're right. – KeaganFouche Jan 10 '22 at 08:37
-3

Don't have your code about the xhr here but it's probably that you're not setting responseType right. Try xhr.responseType = 'blob' before xhr.send().

Also, apart from using FileReader, the following may be more straight forward:

xhr.onreadystatechange = function(){
    if (this.readyState == 4 && this.status == 200){
        var url = window.URL || window.webkitURL;
        img.src = url.createObjectURL(this.response);
    }
}
JJPandari
  • 3,454
  • 1
  • 17
  • 24
  • What? That was not what was asked. They are clearly using something like a video stream and want to turn the blob url into base64 to use elsewhere. – Mitchell Ingram Aug 30 '16 at 15:58