Home > Back-end >  Vue js not rendering image with base64 or binary data from Express API response
Vue js not rendering image with base64 or binary data from Express API response

Time:10-05

My Vue js component receives images via express API call as base64 or raw binary data, but it does not display (render) it.

I can see the image data in the variable given to img src, but for some reason it never renders it, only showing the "broken image icon".

Screenshot of broken image icon

This is the frontend component layout: <img src="srcimg" v-if="srcimg">

The data mounted and watch functions call the async getsrcimg function which makes the Express API call:

  data () {
    return {
      srcimg: null,
...
  mounted () {
    if (this.name) {
      this.getsrcimg(this.name)
    }
  },
  watch: {
    name: function () {
      if (this.name) {
        this.getsrcimg(this.name)
      }
    }
  },

And the function that receives the image via api:

  async getsrcimg (name) {
    try {
      var getImgRes = await axios.post('http://localhost:5000/get_img?img_path='   name)
      const { data } = getImgRes
      this.srcimg = 'data:image/png;base64,'   data
    } catch (err) {
      console.log(err)
      this.message = err.response.data.error
    }
   }

The server backend function:

app.post('/get_img', (req, res) => {
  var img_path = __dirname   req.query.img_path  
  var fs = require('fs');  
  const bitmap = fs.readFileSync(img_path);
  const base64 = new Buffer.from(bitmap).toString("base64");
  res.send(base64);  // Send base64 instead of the raw file binary
});

I can see in the console log, as well as display the this.srcimg data available in this format: data:image/png;base64,77 9UE5HDQoaCg...

But still, the HTML img element does not display the image.

I know the image is being sent correctly because I can see it in the browser inspect Network response preview so it probably is an issue within Vue frontend.

I have also tried to send the image raw binary data from server using res.sendFile and then loading it in the frontend using:

     const blob = new Blob([data], {type: 'image/png'})
     var imgName = 'image_name_example'
     var file = new File([blob], imgName, { type: 'image/png' })
     let reader = new FileReader()
     reader.readAsDataURL(file)
     reader.addEventListener('load', this.processReaderIMG, false)
...
    processReaderIMG: function (readerData) {
      this.srcimg = readerData.target.result
    }

This also gives me the image data but the img element does not display it still.

Any help would be much much appreciated!

CodePudding user response:

If this really is your frontend component:

<img src="srcimg" v-if="srcimg" />

, it attempts to render "srcimg", the actual string, instead of the contents of the reactive variable named srcimg.
And "srcimg" is not a valid source. It's not a url and it's not binary data.

You probably want to use :src instead of src:

<img :src="srcimg" v-if="srcimg" />

, shorthand for

<img v-bind:src="srcimg" v-if="srcimg" />

Docs: v-bind.


If the above is not the issue, test that the binary data is valid (manually). Other possible causes:

  • the binary data might contain line breaks which break the HTML (highly improbable, but worth a check)
  • the response has a different encoding than your page
  • the response is already prefixed with 'data:image/png;base64,'

If everything fails, perhaps you could share the exact response of the server. There has to be something wrong with it, which you're missing.

  • Related