最近做项目,遇到预览PDF这个功能,在网上找了找,大多推荐的是pdf.js,不过在Vue中还是想偷懒直接npm组件,最后找到了一个还不错的Vue-pdf 组件,GitHub地址:https://github.com/FranckFreiburger/vue-pdf#readme
不过一般GitHub上的注释比较简洁,所以这里把自己实际使用的过程总结了一下,下面贴代码
引用: npm install --save vue-pdf
template代码:
1<template> 2 <div class="pdf" v-show="fileType === 'pdf'"> 3 <p class="arrow"> 4 // 上一页 5 <span @click="changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">Preview</span> 6 {{currentPage}} / {{pageCount}} 7 // 下一页 8 <span @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next</span> 9 </p> 10 // 自己引入就可以使用,这里我的需求是做了分页功能,如果不需要分页功能,只要src就可以了 11 <pdf 12 :src="src" // src需要展示的PDF地址 13 :page="currentPage" // 当前展示的PDF页码 14 @num-pages="pageCount=$event" // PDF文件总页码 15 @page-loaded="currentPage=$event" // 一开始加载的页面 16 @loaded="loadPdfHandler"> // 加载事件 17 </pdf> 18 </div> 19</template>
js代码:<script> // 引入PDF
1 import pdf from 'vue-pdf' 2 export default { 3 components: {pdf}, 4 data () { 5 return { 6 currentPage: 0, // pdf文件页码 7 pageCount: 0, // pdf文件总页数 8 fileType: 'pdf', // 文件类型 src: '', // pdf文件地址 9 } 10 }, created: { // 有时PDF文件地址会出现跨域的情况,这里最好处理一下 this.src = pdf.createLoadingTask(this.src) 11 12 } 13 method: { 14 // 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页 15 changePdfPage (val) { 16 // console.log(val) 17 if (val === 0 && this.currentPage > 1) { 18 this.currentPage-- 19 // console.log(this.currentPage) 20 } 21 if (val === 1 && this.currentPage < this.pageCount) { 22 this.currentPage++ 23 // console.log(this.currentPage) 24 } 25 }, 26 27 // pdf加载时 28 loadPdfHandler (e) { 29 this.currentPage = 1 // 加载的时候先加载第一页 30 } 31 32 } 33 } 34 35</script>
实际效果

问题补充: 文件打印乱码问题解决方法
之前有人问了关于PDF打印乱码问题,我自己试了确实有这个问题,在官网找了一下,有人提交了代码解决了这个问题,现在我把方法附上
原始的打印页面,PDF格式乱码,主要是因为PDF里使用了自定义字体,不能识别

需要修改vue-pdf安装包的pdfjsWrapper.js文件

上面后缀为1的文件是原始的,红线框起来的是我修改之后的文件
替换之后,打印就能正常显示了,

博客园貌似不能上传文件,代码太多就不放上来了,如果有需要可以找我邮箱发你,或者到官网自己修改文件

上面提供的解决文件打印乱码的问题,实现起来比较麻烦,而且现在vue-pdf的版本已经更新了,用这个方法可能还会出现空白页的问题.自己在研究了下,用了iframe来预览打印,效果会更好些,这里把方法放上来,有需要的可以试试
这里的例子是把PDF文件放在elment的弹框中,当然你可以根据你自己的适用场景来决定
html:
1<el-dialog 2 :close-on-click-modal="false" 3 :visible.sync="dialogVisible" 4 :fullscreen="true" 5 title="文件预览"> 6 <div class="agreement_picture"> 7 <div class="pdf"> 8 <!-- <pdf // 之前的用PDF插件的方法 9 v-for="i in pdf.numPages" 10 :key="i" 11 :page="i" 12 :src="src"> 13 </pdf> --> 14 // 使用iframe方法 15 <iframe :src="src" frameborder="0" style="width: 100%; height: 100%"></iframe> 16 </div> 17 </div> 18 <span slot="footer" class="dialog-footer"> 19 <div class="tip-left transfer"> 20 <el-button type="info" @click="dialogVisible=false">不同意</el-button> 21 <el-button type="danger" @click="agreeSignFun">同意</el-button> 22 </div> 23 </span> 24 </el-dialog>
js:
1 data () { 2 return { 3 src: '/static/file/中国互联网整体网民发展状况——《第31次中国互联网发展状况调查报告(上)》.pdf', //pdf地址,这里我用的是我本地的文件,你也可以使用后台的文件 4 5 dialogVisible: true 6 } 7 }
效果展示:

打印效果:

现在一般项目为了安全性,不会直接返回文件地址,会返回文件流的格式,对于文件流格式文件可以转化成blob文件,如果有需要可以看下我另一篇博客:文件流数据如何转blob文件 https://www.cnblogs.com/steamed-twisted-roll/p/11821148.html