Requesting blob images and transforming to base64 with fetch API
Asked Answered
R

4

28

I have some images that will be displayed in a React app. I perform a GET request to a server, which returns images in BLOB format. Then I transform these images to base64. Finally, i'm setting these base64 strings inside the src attribute of an image tag.

Recently I've started using the Fetch API. I was wondering if there is a way to do the transforming in 'one' go.

Below an example to explain my idea so far and/or if this is even possible with the Fetch API. I haven't found anything online yet.

  let reader = new window.FileReader();
  fetch('http://localhost:3000/whatever')
  .then(response => response.blob())
  .then(myBlob => reader.readAsDataURL(myBlob))
  .then(myBase64 => {
    imagesString = myBase64
  }).catch(error => {
    //Lalala
  })
Razorbill answered 22/6, 2017 at 12:4 Comment(3)
Why not use a blob url, or just the original urlBrunhilda
I'm not using the URL in the src because the images I get are coming from an API that requires an authentication token in the header.Razorbill
stackoverflow.com/questions/6150289/…Procession
S
35

The return of FileReader.readAsDataURL is not a promise. You have to do it the old way.

fetch('http://localhost:3000/whatever')
.then( response => response.blob() )
.then( blob =>{
    var reader = new FileReader() ;
    reader.onload = function(){ console.log(this.result) } ; // <--- `this.result` contains a base64 data URI
    reader.readAsDataURL(blob) ;
}) ;

General purpose function:

function urlContentToDataUri(url){
    return  fetch(url)
            .then( response => response.blob() )
            .then( blob => new Promise( callback =>{
                let reader = new FileReader() ;
                reader.onload = function(){ callback(this.result) } ;
                reader.readAsDataURL(blob) ;
            }) ) ;
}

//Usage example:
urlContentToDataUri('http://example.com').then( dataUri => console.log(dataUri) ) ;

//Usage example using await:
let dataUri = await urlContentToDataUri('http://example.com') ;
console.log(dataUri) ;
Stinker answered 22/5, 2018 at 8:23 Comment(3)
How do you return that from a function?Olmos
@Reinstate, You can't return it directly. You have to return a Promise instead. See updated answer.Stinker
I see. I was only familiar with Promise.resolve and not yet familiar with new Promise(resolve=> ... resolve(value); ...); although now it seems obvious. Thank you!Olmos
R
11

Thanks to @GetFree, here's the async/await version of it, with promise error handling:

const imageUrlToBase64 = async url => {
  const response = await fetch(url);
  const blob = await response.blob();
  return new Promise((onSuccess, onError) => {
    try {
      const reader = new FileReader() ;
      reader.onload = function(){ onSuccess(this.result) } ;
      reader.readAsDataURL(blob) ;
    } catch(e) {
      onError(e);
    }
  });
};

Usage:

const base64 = await imageUrlToBase64('https://via.placeholder.com/150');
Remount answered 24/3, 2022 at 14:51 Comment(0)
L
2

If somebody gonna need to do it in Node.js:

const fetch = require('cross-fetch');
const response  = await fetch(url);
const base64_body = (await response.buffer()).toString('base64');
Larrisa answered 28/1, 2022 at 12:28 Comment(1)
or just use node-fetch instead of cross-fetchAryl
S
1

Here's the logic for converting a blob to an image URI, derived from @Augustin Riedinger's answer:

async function imageUrlToBase64(blob: Blob) {
  return new Promise((onSuccess, onError) => {
    try {
      const reader = new FileReader();
      reader.onload = function () {
        onSuccess(this.result);
      };
      reader.readAsDataURL(blob);
    } catch (e) {
      onError(e);
    }
  });
}

Usage:

const res = await fetch(...);
const blob = await res.blob();
const uri = await imageBlobToBase64(blob);
Spunky answered 14/9, 2023 at 1:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.