pdfjs-dist预览pdf文件

该博客展示了如何在Vue应用中利用pdfjs-dist库来预览PDF文件。通过循环遍历页面并在canvas元素上渲染,实现了逐页显示PDF内容。同时,提供了加载状态提示及下载文件的功能。文章详细讲解了代码实现过程,包括设置全局worker源、获取PDF文档、渲染页面以及监听文件加载等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pdfjs-dist预览pdf

<template>
  <div class="view">
    <template v-for="item in pageNum" :key="item">
      <canvas :id="`pdf-canvas-${item}`" class="pdf-page" />
    </template>
  </div>
  <!-- <div class="footer">
    <Button color="#006BE1" type="primary" @click="downLoadPDF" class="btn">
      下载文件
    </Button>
  </div> -->
</template>

<script setup lang="ts">
import { reactive, toRefs, nextTick, watchEffect, defineProps } from "vue";
//@ts-ignore
import * as pdfjs from "pdfjs-dist";
//@ts-ignore
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
import { Toast, Button } from "vant";
// import { downloadFile } from "@/utils";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
const props = defineProps({
  url: { type: String, default: "" }, // pdf文件路径
});

const emit = defineEmits(["onRendered"]);
const state = reactive<any>({
  pageNum: 0,
  pdfCtx: null,
});

const resolvePdf = (url: string) => {
  const loadingTask = pdfjs.getDocument(url);
  loadingTask.promise.then((pdf: any) => {
    state.pdfCtx = pdf;
    state.pageNum = pdf.numPages;
    nextTick(() => {
      renderPdf();
    });
  });
};

const renderPdf = (num = 1) => {
  state.pdfCtx.getPage(num).then((page: any) => {
    const canvas: any = document.getElementById(`pdf-canvas-${num}`);
    const ctx = canvas.getContext("2d");
    const viewport = page.getViewport({ scale: 1 });
    // 画布大小,默认值是width:300px,height:150px
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕
    const clientWidth = document.body.clientWidth;
    canvas.style.width = clientWidth + "px";
    // 根据pdf每页的宽高比例设置canvas的高度
    canvas.style.height =
      clientWidth * (viewport.height / viewport.width) + "px";
    page.render({
      canvasContext: ctx,
      viewport,
    });
    if (num < state.pageNum) {
      renderPdf(num + 1);
    } else {
      emit("onRendered");
      Toast.clear(); // 取消加载loading
    }
  });
};

watchEffect(() => {
  if (props.url) {
    // 展示加载loading
    Toast.loading({
      message: "加载中...",
      overlay: true,
      forbidClick: true,
      duration: 0,
    });

    resolvePdf(props.url);
  }
});

const { pageNum, pdfCtx } = toRefs(state);
</script>
<style scoped>
 .view {
  padding-bottom: 1.5rem;
}
.footer {
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 0.16rem 0.4rem 0.6rem;
  display: flex;
  align-items: center;
  height: 1.5rem;
  box-shadow: 0px -1px 0px rgba(49, 69, 106, 0.164254);
  background-color: #fff;
}
.btn {
  width: 100%;
}
.van-button {
  border-radius: 0.1rem;
} 
</style>
### 使用 `pdfjs-dist` 库在 Vue 项目中实现 PDF 文件预览 #### 安装依赖包 为了能够在 Vue 项目中使用 `pdfjs-dist` 来加载并渲染 PDF 文档,首先需要安装必要的 npm 包: ```bash npm install pdfjs-dist --save ``` 此命令会下载 `pdfjs-dist` 及其所需的相关资源到项目的 node_modules 目录下[^1]。 #### 导入 PDF.js 并配置全局变量 接着,在 main.js 或者相应的入口文件里引入 PDF.js 的核心模块,并设置全局路径以便于后续操作: ```javascript import * as pdfjsLib from 'pdfjs-dist'; // 如果需要 Web Worker 支持,则还需要额外导入 worker 文件 import 'pdfjs-dist/build/pdf.worker.entry'; // 设置 PDFJS 工具的默认参数 pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.min.js', import.meta.url, ).toString(); ``` 这段代码确保了当解析较大的 PDF 文件时可以利用多线程加速性能[^3]。 #### 创建组件用于显示 PDF 页面 创建一个新的单文件组件 (SFC),比如命名为 PdfViewer.vue ,用来负责呈现具体的 PDF 内容。在这个组件内部定义方法去获取远程或本地存储的 PDF 数据源,并逐页绘制出来: ```html <template> <div class="pdf-viewer"> <!-- 动态生成 canvas 标签 --> <canvas v-for="(page, index) in pages" :key="index"></canvas> </div> </template> <script setup lang="ts"> import { ref } from "vue"; import * as pdfjsLib from "pdfjs-dist"; const props = defineProps({ url: String // 接收外部传递过来的 PDF 路径作为 prop 属性 }); let loadingTask; let numPages = ref(0); let pages = []; async function loadPdf() { try { const response = await fetch(props.url); const arrayBuffer = await response.arrayBuffer(); // 加载 PDF 文档对象 loadingTask = pdfjsLib.getDocument(arrayBuffer); const pdfDocument = await loadingTask.promise; numPages.value = pdfDocument.numPages; for (let pageNumber = 1; pageNumber <= numPages.value; ++pageNumber) { renderPage(pdfDocument, pageNumber); } } catch (error) { console.error("Error while loading the document:", error); } } function renderPage(doc, pageNum) { doc.getPage(pageNum).then((page) => { let viewport = page.getViewport({ scale: 1.5 }); // 准备画布容器 var canvas = document.createElement('CANVAS'); var context = canvas.getContext('2d'); // 配置 Canvas 尺寸匹配页面大小 canvas.height = viewport.height; canvas.width = viewport.width; // 插入新创建好的 Canvas 到 DOM 结构内 document.querySelector('.pdf-viewer').appendChild(canvas); // 渲染当前页面至指定上下文中 var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); } </script> <style scoped> .pdf-viewer { display: flex; flex-direction: column; align-items: center; } </style> ``` 上述模板展示了如何构建一个简单的 PDF 查看器,它能够接收来自父级组件或者其他地方传来的 PDF 文件链接,并将其内容一页接一页地呈现在界面上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值