赞
踩
demo使用的vue为3.4.21,pdfjs-dist为4.3.136,pdf-lib为1.17.1。
npm i pdfjs-dist pdf-lib
<template> <div class="pdf-wrapper"> <div ref="pdfContainer" class="pdf-container" @mousedown="onMouseDown"> <!-- PDF的canvas将会插入到这里 --> </div> <div class="controls"> <button @click="prevPage">上一页</button> <button @click="nextPage">下一页</button> <button @click="zoomIn">放大</button> <button @click="zoomOut">缩小</button> <button @click="downloadPDF">下载</button> </div> <div class="page-wrapper"> 当前第{{ currentPage }}页,共{{ totalPages }}页 </div> </div> </template>
其中需要注意的部分是pdfjsLib.GlobalWorkerOptions.workerSrc会查到多种写法,大多数是引人的在线js,对于内网或者无互联网环境不友好,且因为版本问题无法直接替换引入的url中的版本。demo中使用的是安装的依赖中的js。(若版本不同导致报错,可评论探讨)
import { ref, onMounted } from "vue"; import * as pdfjsLib from "pdfjs-dist"; import * as workerSrc from "pdfjs-dist/build/pdf.worker.min?url"; import { PDFDocument } from "pdf-lib"; // demo的pdf的路径是从父组件传入在onMounted中进行赋值 const props = defineProps(["src"]); // 配置 PDF.js worker 的路径 pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc.default; const pdfContainer = ref(null); // pdf容器 const pdfUrl = ref(""); // 可替换为你的 PDF 文件路径 let pdfDoc = null; // pdf显示内容 let scale = ref(1.0); // 缩放比例 let currentPage = ref(1); // 当前页 let totalPages = ref(0); // 总页数 let isDragging = ref(false); // 是否可拖拽 let startX = ref(0); // 拖拽的x轴 let startY = ref(0); // 拖拽的y轴 let scrollLeft = ref(0); // 滚动的left let scrollTop = ref(0); // 滚动的top onMounted(async () => { //对pdf的url进行赋值 pdfUrl.value = props.src; //使用pdfjs-dist对pdf进行解析,该步骤为异步 const loadingTask = pdfjsLib.getDocument(pdfUrl.value); pdfDoc = await loadingTask.promise; //获取到总页数 totalPages.value = pdfDoc.numPages; //使用渲染方法 renderPage(currentPage.value); }); //渲染方法() const renderPage = async (num) => { const page = await pdfDoc.getPage(num); const viewport = page.getViewport({ scale: scale.value }); const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext: context, viewport: viewport, }; await page.render(renderContext).promise; pdfContainer.value.innerHTML = ""; pdfContainer.value.appendChild(canvas); }; //放大 const zoomIn = () => { scale.value += 0.1; renderPage(currentPage.value); }; //缩小 const zoomOut = () => { if (scale.value > 0.2) { scale.value -= 0.1; renderPage(currentPage.value); } }; //下一页 const nextPage = () => { if (currentPage.value < totalPages.value) { currentPage.value += 1; renderPage(currentPage.value); } }; //上一页 const prevPage = () => { if (currentPage.value > 1) { currentPage.value -= 1; renderPage(currentPage.value); } }; //下载 const downloadPDF = async () => { const existingPdfBytes = await fetch(pdfUrl.value).then((res) => res.arrayBuffer() ); const pdfDoc = await PDFDocument.load(existingPdfBytes); const pdfBytes = await pdfDoc.save(); const blob = new Blob([pdfBytes], { type: "application/pdf" }); const link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = "downloaded.pdf"; link.click(); }; //用于实现拖拽 //鼠标按下 const onMouseDown = (e) => { isDragging.value = true; startX.value = e.pageX - pdfContainer.value.offsetLeft; startY.value = e.pageY - pdfContainer.value.offsetTop; scrollLeft.value = pdfContainer.value.scrollLeft; scrollTop.value = pdfContainer.value.scrollTop; document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); }; //鼠标移动 const onMouseMove = (e) => { if (!isDragging.value) return; const x = e.pageX - pdfContainer.value.offsetLeft; const y = e.pageY - pdfContainer.value.offsetTop; const walkX = x - startX.value; const walkY = y - startY.value; pdfContainer.value.scrollLeft = scrollLeft.value - walkX; pdfContainer.value.scrollTop = scrollTop.value - walkY; }; //鼠标抬起 const onMouseUp = () => { isDragging.value = false; document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); };
.pdf-wrapper { width: 100%; height: 100%; position: relative; display: flex; flex-direction: column; align-items: center; } .pdf-container { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; overflow: auto; cursor: grab; } .pdf-container:active { cursor: grabbing; } .controls { position: absolute; top: 10px; left: 10px; display: flex; justify-content: center; gap: 10px; margin-top: 10px; } button { padding: 5px 10px; cursor: pointer; } .page-wrapper { font-size: 20px; color: #fff; }
gitee地址:https://gitee.com/dasl1412/pdf-view
更新一下小问题
[2024.6.28]
在实际使用时以上内容本地使用没有问题,但当部署在服务器之后(目前只是用了nginx进行部署),预览时会报错,报错如下:
这时候可以通过在nginx.conf内一下配置,可正常使用。(nginx -t检查配置时可能会报警告,目前暂未研究,nginx比较菜,如有大神可评论区指点)
types {
text/javascript js mjs;
}
[2024.7.9]
使用中发现了一下问题,由于篇幅问题,新写了一篇文章,若有使用该封装遇到问题的,可以移步查看是否是相似问题,若出现其他问题可以评论区讨论。(基于pdfjs-dist和pdf-lib实现PDF的预览(缩放、下载)(二))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。