1

I have a GET request with axios and get a .png file back and want to show this inside my template. I can't use a path url, because the image is each time differently.

This is my fastapi route.

from io import BytesIO
from fastapi.responses import Response


@app.get("/image", response_class=Response)
def load_image():
    ...
    buffer = BytesIO()
    img.save(buffer, format="PNG")

    return Response(content=buffer.getvalue(), media_type="image/png")

This is the vue component:

<script>
export default {
  name: "Example",
  data() {
    return {
      image: null;
    };
  },
  methods: {
    async loadImage() {
      const url = "/image";
      const response = await $axios.get(url, { responseType: "arraybuffer" });
      if (response.status == 200) {
        const base64string = btoa(String.fromCharCode(...new Uint8Array(response.data)));
        console.log(base64string); // -> this is a empty string
        this.image = 'data:image/png;base64,' + base64string;
      }
  },
  mounted() {
    this.loadImage();
  },
};
</script>

<template>
  <div>
    <img :src="image" title="Image" />
  </div>
</template>
6
  • 1
    Can you post what this.image actually contains? Either from the response or console.log might be helpful. As for <img> tag, you need a string for src attribute. Commented Sep 28, 2022 at 22:37
  • this.image= "�PNG \n\n IHDR���G!�IDATx��An�HE?G�,}�E�A��H}�(9@i@gQ�"ewϠ���........" Commented Sep 28, 2022 at 22:41
  • 1
    That is what I expected. So you are right. The response is the problem. I guess if you access the URL directly in the browser you are getting the image as it should be. IMO, use base64 encoding for the images if possible ( commonly used with dynamic images). You will get a base64 URL which you can directly use in src Commented Sep 28, 2022 at 22:47
  • 1
    Related answers can also be found here, as well as here and here. Commented Sep 29, 2022 at 4:20
  • 1
    Please have a look at this answer and this answer on how to return a Response with image bytes held in an in-memory buffer from FastAPI backend. Commented Sep 29, 2022 at 10:52

1 Answer 1

2

You can...

  • get the data as a blob by passing { responseType: "blob" } to axios
  • convert the blob to base64 with FileReader (used blobToData function from https://stackoverflow.com/a/63372663/197546)
  • use the base64 data as the image src

example:

const app = Vue.createApp({
  data() {
    return {
      imageSrc: null,
    };
  },
  methods: {
    async loadImage() {
      const url =
        "https://images.unsplash.com/photo-1664300067908-84e8beb52a8f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyNXx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60";
      const response = await axios.get(url, { responseType: "blob" });
      if (response.status == 200) {
        const base64data = await blobToData(response.data);
        this.imageSrc = base64data;
      }
    },
  },
  mounted() {
    this.loadImage();
  },
});

app.mount("app");

function blobToData(blob) {
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.readAsDataURL(blob)
  })
}
<script src="https://unpkg.com/vue@next/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<app>
 <img :src="imageSrc" v-if="imageSrc"/>
</app>


As Chris pointed out, you can also...

  • get the data as an array buffer by passing { responseType: "arraybuffer" } to axios
  • convert array to base64 data using btoa(String.fromCharCode(...new Uint8Array(response.data)))
  • build the src data by adding prepending the content type to the base64 data

example:

const app = Vue.createApp({
  data() {
    return {
      imageSrc: null,
    };
  },
  methods: {
    async loadImage() {
      const url =
        "https://images.unsplash.com/photo-1664300067908-84e8beb52a8f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyNXx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60";
      const response = await axios.get(url, { responseType: "arraybuffer" });
      if (response.status == 200) {
        const b64 = btoa(String.fromCharCode(...new Uint8Array(response.data)));
        const imgData = "data:" + response.headers['content-type'] + ";base64," + b64;
        this.imageSrc = imgData;
      }
    },
  },
  mounted() {
    this.loadImage();
  },
});

app.mount("app");
<script src="https://unpkg.com/vue@next/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<app>
 <img :src="imageSrc" v-if="imageSrc"/>
</app>

Sign up to request clarification or add additional context in comments.

1 Comment

Getting a blob object and then converting it into base64 format makes little sense. You can simply create a URL out of the blob object and use that as the image src; otherwise, if you would like to get the image in base64 format in the first place, use responseType: "arraybuffer" and btoa() method to create a base64-encoded string. Please have a look at this answer for more details and examples.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.