I have a Dialog in my vue project to display a PDF file. This is how the parent component handles the PDF file.
async function openDialog(index: number) {
isLoading.value = true;
const selectedEbook = listEbook.value[index];
const originalUrl = selectedEbook.url;
if (!originalUrl) {
console.warn("URL tidak tersedia untuk item ini");
isLoading.value = false;
return;
}
const isDev = import.meta.env.MODE === "development";
const fileUrl = isDev
? originalUrl.replace("https://main-url.com", "/api-pdf")
: originalUrl;
if (!fileUrl) return;
try {
const response = await axios.get(fileUrl, {
responseType: "blob",
});
if (!response) throw new Error("Gagal fetch file PDF");
if (selectedBlobUrl.value) {
URL.revokeObjectURL(selectedBlobUrl.value);
}
// this condition to check the selectedEbook url, because there is 2 different url,
// the one is generated pdf from API and another one is static pdf from FTP server
if (selectedEbook.icon != "pi-file-pdf") {
const blob = new Blob([response.data], { type: "application/pdf" });
selectedBlobUrl.value = URL.createObjectURL(blob);
} else {
const url = URL.createObjectURL(
new Blob([response.data], {
type: "application/pdf",
})
);
selectedBlobUrl.value = url;
}
console.log(selectedBlobUrl.value);
pdfDialog.value = true;
} catch (err) {
console.error("Gagal membuka PDF:", err);
} finally {
isLoading.value = false;
}
}
And this is how the child component handles it
<template>
<Dialog
v-model:visible="visible"
modal
header="Lihat Dokumen"
:style="{ width: '100%', height: '100%' }"
:breakpoints="{ '1199px': '75vw', '575px': '90vw' }"
>
<VuePdfEmbed
annotation-layer
text-layer
:source="props.url"
class="shadow-3"
/>
</Dialog>
</template>
<script setup lang="ts">
import { computed, watch } from "vue";
import VuePdfEmbed from "vue-pdf-embed";
import "vue-pdf-embed/dist/styles/annotationLayer.css";
import "vue-pdf-embed/dist/styles/textLayer.css";
const props = defineProps<{
url: string | null;
modelValue: boolean;
}>();
const emits = defineEmits<{
(e: "update:modelValue", value: boolean): void;
}>();
const visible = computed({
get: () => props.modelValue,
set: (value) => emits("update:modelValue", value),
});
watch(
() => props.url,
(value) => {
if (value) {
// Handle the non-null value of props.url here
console.log(value);
}
}
);
</script>
In development mode, the PDF is work properly. But in production, the PDF can't show on Dialog. What I have try is, actually i was using pdfjs-dist but then my friend suggested me to use vue-pdf-embed because I was using Vue in project. I appreciate for the answer
After some search, the answer is changing the Content-Dispotition from the response header of the PDF url from 'attachment' to 'inline'.