vue.jspdfvuejs3primevuepdfjs-dist

How to display static pdf url with vue-pdf-embed library on production


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


Solution

  • After some search, the answer is changing the Content-Dispotition from the response header of the PDF url from 'attachment' to 'inline'.