Vue3+pdfjs-dist实现PDF文件展示

本文详细描述了如何使用Vue3和pdfjs-dist库在Web应用中渲染PDF文件,包括安装、页面结构搭建、数据声明、获取PDF文档流、渲染PDF页面以及处理本地文件安全问题。作者分享了从实际项目中学习和实现PDF文件多页展示的具体步骤。

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

前言:最近和小伙伴们一起合作完成一个面试推送系统的书写,其中一个功能就是渲染PDF文件,展示用户上传的面经,干了整整一周,终于实现了这个功能,现在将自己实现的过程分享给大家.

1.pdfjs-dist展示PDF文件的原理解释

pdfjs-dist展示pdf文档的原理,实际上是将pdf中的内容渲染到解析,然后渲染到 canvas 中进行展示,因此我们使用pdfjs渲染出来的pdf文件,实际上是一张张canvas图片。

2.安装pdfjs-dist

pdfjs-dist下载官网

打开VScode,使用ctl+`打开控制台,输入:npm i pdfjs-dist 安装pdfjs-dist

3. 搭建基础的页面代码

话不多说,上代码:

<template>
        <div class="interviewVideo_main" id="videoContainer">
        <!--此处根据pdf的页数动态生成相应数量的canvas画布-->
        <canvas
          v-for="pageIndex in pdfPages"
          :id="`pdf-canvas-` + pageIndex"
          :key="pageIndex"
          style="display: block"
        ></canvas>
       </div>
</template>

4.使用Vue3语法实现PDF文件的多页展示

4.1引入ref、pdfjs-dist
import { ref, reactive, onMounted, nextTick } from "vue";
//注意引入的写法
import * as pdfjsLib from "pdfjs-dist/build/pdf";
4.2将会用到的数据声明为响应式
let pdfDoc = reactive({}); // 保存加载的pdf文件流
let pdfPages = ref(0); // pdf文件的页数
//pdf文件的链接
let pdfUrl = ref("需要展示的文件名"); 
let pdfScale = ref(1.0); // 缩放比例
4.3定义获取pdf文档流与pdf文件的页数的方法:loadFile
//获取pdf文档流与pdf文件的页数
const loadFile = async (url) => {
//注意我的pdfjs-dist的版本是3.9.179,其他的版本需要更换版本号,不然运行时会报版本不匹配的错
//外部链接引入,存在安全性问题
//pdfjsLib.GlobalWorkerOptions.workerSrc =
//"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.9.179/pdf.worker.min.js";
//内部链接引入
  pdfjsLib.GlobalWorkerOptions.workerSrc =
    "../../node_modules/pdfjs-dist/build/pdf.worker.min.js";
  const loadingTask = pdfjsLib.getDocument(url);
  loadingTask.promise.then((pdf) => {
    console.log(pdf);
    pdfDoc = pdf;                 //获取pdf文档流
    pdfPages.value = pdf.numPages;//获取pdf文件的页数
    nextTick(() => {
      renderPage(1);
    });
  });
};
4.4定义渲染pdf文件的方法:renderPage
const renderPage = (num) => {
  pdfDoc.getPage(num).then((page) => {
    const canvasId = "pdf-canvas-" + num;
    const canvas = document.getElementById(canvasId);
    const ctx = canvas.getContext("2d");
    const dpr = window.devicePixelRatio || 1;
    const bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
    const ratio = dpr / bsr;
    const viewport = page.getViewport({ scale: pdfScale.value });
    canvas.width = viewport.width * ratio;
    canvas.height = viewport.height * ratio;
    canvas.style.width = viewport.width + "px";
    canvas.style.height = viewport.height + "px";
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    page.render(renderContext);
    if (num < pdfPages.value) {
      renderPage(num + 1);
    }
  });
};
4.5在onMounted钩子中调用loadFile方法
//调用loadFile方法
onMounted( () => {
  loadFile(pdfUrl.value);
});

5完整代码实现:

<template>
        <div class="interviewVideo_main" id="videoContainer">
        <!--此处根据pdf的页数动态生成相应数量的canvas画布-->
        <canvas
          v-for="pageIndex in pdfPages"
          :id="`pdf-canvas-` + pageIndex"
          :key="pageIndex"
          style="display: block"
        ></canvas>
       </div>
</template>
<script setup>
import { ref } from "vue";
import * as pdfjsLib from "pdfjs-dist/build/pdf";
let pdfDoc = reactive({}); // 保存加载的pdf文件流
let pdfPages = ref(0); // pdf文件的页数
let pdfUrl = ref(""); //pdf文件的链接
let pdfScale = ref(1.0); // 缩放比例
//调用loadFile方法
onMounted(() => {
  loadFile(pdfUrl.value);
});
//获取pdf文档流与pdf文件的页数
const loadFile = async (url) => {
  pdfjsLib.GlobalWorkerOptions.workerSrc =
    "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.9.179/pdf.worker.min.js";
  const loadingTask = pdfjsLib.getDocument(url);
  loadingTask.promise.then((pdf) => {
    console.log(pdf);
    pdfDoc = pdf;
    pdfPages.value = pdf.numPages;
    nextTick(() => {
      renderPage(1);
    });
  });
};
//渲染pdf文件
const renderPage = (num) => {
  pdfDoc.getPage(num).then((page) => {
    const canvasId = "pdf-canvas-" + num;
    const canvas = document.getElementById(canvasId);
    const ctx = canvas.getContext("2d");
    const dpr = window.devicePixelRatio || 1;
    const bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
    const ratio = dpr / bsr;
    const viewport = page.getViewport({ scale: pdfScale.value });
    canvas.width = viewport.width * ratio;
    canvas.height = viewport.height * ratio;
    canvas.style.width = viewport.width + "px";
    canvas.style.height = viewport.height + "px";
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    page.render(renderContext);
    if (num < pdfPages.value) {
      renderPage(num + 1);
    }
  });
};
</script>
<style>
#videoContainer {
  height: 842px;
}
</style>

以上就是实现PDF文件多页展示的内容了,如果其他的小伙伴有其他的方法或者思考请批评指正 

6.使用本地文件

如果直接引用本地PDF文件,浏览器会报错:network.js:101 Not allowed to load local resource

原因如下:

浏览器的安全策略禁止直接加载本地文件。这是浏览器的安全限制,旨在防止恶意代码读取用户的本地文件系统。

处理方法:

1.将本地的PDF文件,放在public文件夹下,然后直接引用文件链接即可

2.放在assets文件下,使用import引入项目

我采用的方法是配合后端,将所有的PDF文件存放在阿里云中,借助第三方增加安全性,如果在使用阿里云存放后,报错:

可以依据阿里云官方提供的配置文件进行配置,链接如下:
阿里云文件跨域配置

Vue3中使用pdfjs-dist是为了查看PDF文档。首先,需要安装pdfjs-dist依赖,可以通过运行npm i pdfjs-dist命令进行安装。然后,在Vue3中使用pdfjs-dist的基本页面代码如下: ```html <template> <div class="pdf-container"> <canvas id="pdf-canvas"></canvas> </div> </template> <script lang="ts"> import { Options, Vue } from &#39;vue-class-component&#39; import * as PdfJs from &#39;pdfjs-dist/legacy/build/pdf.js&#39; import Pdf from &#39;@/assets/js.pdf&#39; @Options({}) export default class SinglePage extends Vue { loadFile(url: string): void { PdfJs.GlobalWorkerOptions.workerSrc = require(&#39;pdfjs-dist/build/pdf.worker.entry&#39;) const loadingTask = PdfJs.getDocument(url) loadingTask.promise.then((pdf) => { this.pdfDoc = pdf this.pdfPages = this.pdfDoc.numPages this.$nextTick(() => { this.renderPage(1) }) }) } } </script> ``` 在上述代码中,loadFile()方法用于加载PDF文件,并渲染到canvas上。需要注意的是,加载PDF文件前需要设定pdfjs的workerSrc参数,否则可能会出现workerSrc未定义的错误。通过loadingTask.promise可以获取加载的PDF文件流,并保存到pdfDoc变量中,同时获取PDF文件的总页数。最后,调用renderPage()方法将PDF文件内容渲染到canvas上。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [超详细的vue3使用pdfjs教程](https://blog.csdn.net/CherishTheYouth/article/details/119619608)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值