Reputation: 2785
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>
Upvotes: 1
Views: 2941
Reputation: 35724
You can...
{ responseType: "blob" }
to axiosFileReader
(used blobToData function from https://stackoverflow.com/a/63372663/197546)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...
{ responseType: "arraybuffer" }
to axiosbtoa(String.fromCharCode(...new Uint8Array(response.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>
Upvotes: 2