React: Display an image converted to base64

Viewed 341

I'm having a hard time displaying an image sent by my Node/Express server to my React app. I tried perusing the solutions in other SO's questions, but I could'nt get it to work. Here are my steps

  1. My Node/Express server sends the image
router.get('/:file_id', (req, res) => {
   //... Query file information //
   const filePath = `${config.FILE_STORAGE}/${doc._id}`;
   res.sendFile(filePath);
});
  1. My image is sent correctly enter image description here

  2. I decoded it with React

axiosInstance.get(`/files/${document.file}`)
    .then((response) => {
      const image_base64 = Buffer.from(response.data).toString('base64');
      setThumbnail(image_base64);
})
  1. And inserted it in an img tag
<img src={`data:image/jpg;base64,${thumbnail}`}

But the image doesn't display. I did some additional verifications :

  • I manually inserted in <img> an image that I base64 encoded using an online converter, and it displayed.
  • I copied the base64 image encoded in step (3) in an online decoder, and it couldn't decode it. So the problem is clearly in either reading the response data or encoding it in base64. Can you help? thanks!
1 Answers

You can use this function to generate the base64 string. It works fine for me. The function is given below:

function base64ArrayBuffer(byteArray) {
  var base64 = "";
  var encodings =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  var bytes = byteArray;
  var byteLength = bytes.byteLength;
  var byteRemainder = byteLength % 3;
  var mainLength = byteLength - byteRemainder;

  var a, b, c, d;
  var chunk;

  // Main loop deals with bytes in chunks of 3
  for (var i = 0; i < mainLength; i = i + 3) {
    // Combine the three bytes into a single integer
    chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];

    // Use bitmasks to extract 6-bit segments from the triplet
    a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
    b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12
    c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6
    d = chunk & 63; // 63       = 2^6 - 1

    // Convert the raw binary segments to the appropriate ASCII encoding
    base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
  }

  // Deal with the remaining bytes and padding
  if (byteRemainder == 1) {
    chunk = bytes[mainLength];

    a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2

    // Set the 4 least significant bits to zero
    b = (chunk & 3) << 4; // 3   = 2^2 - 1

    base64 += encodings[a] + encodings[b] + "==";
  } else if (byteRemainder == 2) {
    chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];

    a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
    b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4

    // Set the 2 least significant bits to zero
    c = (chunk & 15) << 2; // 15    = 2^4 - 1

    base64 += encodings[a] + encodings[b] + encodings[c] + "=";
  }

  return base64;
}

So, in your case the code should be:

axiosInstance.get(`/files/${document.file}`)
    .then((response) => {
      const image_base64 = base64ArrayBuffer(Buffer.from(response.data));
      setThumbnail(image_base64);
})
Related