pdfjs-dist 实现pdf文件在线预览
- 实现效果
- 实现过程
- (1)安装pdfjs-dist
- (2)代码部分
- (3)原理
项目要求实现pdf文件在线预览,并且pdf预览通过上下页滚动pdf,且兼容ie浏览器
浏览器兼容参照了 这位博主的文章,选择用pdfjs-dist 实现
实现效果
这是我随便写的一个pdf(一共2页),可通过点击上下换页
谷歌浏览器
ie11
实现过程
(1)安装pdfjs-dist
npm install --save pdfjs-dist@2.0.943
这里需要指定2.0.943的版本,试过其他版本的都会多多少少在引入,执行行数时报错
(2)代码部分
<template><div class="main-container"><input type="file" ref="fielinput" @change="uploadFile" /><div class="canvas-container"><canvas ref="myCanvas" class="pdf-container"> </canvas></div><div class="pagination-wrapper"><button @click="clickPre">上一页</button><span>第{{ pageNo }} / {{ pdfPageNumber }}页</span><button @click="clickNext">下一页</button></div></div>
</template><script>
const pdfJS = require("pdfjs-dist");pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
export default {mounted() {},data() {return {pageNo: null,pdfPageNumber: null,pdfTotalPages: 1,renderingPage: false,pdfData: null, // PDF的base64scale: 1, // 缩放值};},methods: {uploadFile() {let inputDom = this.$refs.fielinput;let file = inputDom.files[0];let reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {let data = atob(reader.result.substring(reader.result.indexOf(",") + 1));this.loadPdfData(data);};},loadPdfData(data) {// 引入pdf.js的字体let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";//读取base64的pdf流文件this.pdfData = pdfJS.getDocument({data: data, // PDF base64编码cMapUrl: CMAP_URL,cMapPacked: true,});console.log(this.pdfData);this.renderPage(1);this.renderScrollPdf();},// 根据页码渲染相应的PDFrenderPage(num) {this.renderingPage = true;this.pdfData.promise.then((pdf) => {this.pdfPageNumber = pdf.numPages;pdf.getPage(num).then((page) => {// 获取DOM中为预览PDF准备好的canvasDOM对象let canvas = this.$refs.myCanvas;let viewport = page.getViewport(this.scale);canvas.height = viewport.height;canvas.width = viewport.width;let ctx = canvas.getContext("2d");let renderContext = {canvasContext: ctx,viewport: viewport,};page.render(renderContext).then(() => {this.renderingPage = false;this.pageNo = num;});});});},clickPre() {if (!this.renderingPage && this.pageNo && this.pageNo > 1) {this.renderPage(this.pageNo - 1);}},clickNext() {if (!this.renderingPage &&this.pdfPageNumber &&this.pageNo &&this.pageNo < this.pdfPageNumber) {this.renderPage(this.pageNo + 1);}},renderScrollPdf() {this.pdfData.promise.then((pdf) => {this.pdfTotalPages = pdf.numPages;this.renderScrollPdfPage(1);});},},
};
</script><style scoped>
.main-container {display: flex;flex-direction: column;align-items: center;
}
.canvas-container {width: 400px;height: 500px;border: 1px dashed black;position: relative;display: flex;justify-content: center;
}
.scroll-pdf-contanier {width: 400px;height: 500px;border: 1px dashed black;position: relative;display: flex;flex-direction: column;overflow-y: scroll;
}
.pdf-container {width: 100%;height: 100%;
}
.scroll-pdf-container {width: 350px;
}
.pagination-wrapper {display: flex;justify-content: center;align-items: center;
}
</style>
(3)原理
首先是要传递给pdfjs-dist展示的是以base64的方式传递,这里用了上传文件,将文件流转化成base64进行模拟,一般是由后台传给前端base64数据直接渲染
uploadFile() {let inputDom = this.$refs.fielinput;let file = inputDom.files[0];let reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {let data = atob(reader.result.substring(reader.result.indexOf(",") + 1));this.loadPdfData(data);};},
loadPdfData函数接受到base64数据后,调用pdf-dist的方法将pdf转换成canvas,相当于用图片的方式展示pdf,而各个浏览器都支持图片,那么就少了很多兼容的问题了
再配合pdf的页数,点击按钮上下切换,功能基本实现