作为一个后端开发,写前端的一些功能也是头大,好在网友强大,网上资源比较多;做一个移动端PDF预览的功能,本来可以通过window.open(),打开的,但是没办法,做后台的小伙伴,传给前端的数据是base64位,我只能按照后台给的数据进行处理了;
方法一:
最原始的方式:通过canvas将字节流转成图片,方法简单,别人的代码直接抄过来就能用;但是缺点也同样严重,图片展示清晰度很低;
代码如下
1.安装依赖
npm install pdfjs-dist
2.template代码:
<template> <div style="background-color:white;height:100%;"> <div class="v-viewbtns"> <div style="position:relative"> <button @click="scaleAdd">+</button> <button @click="scaleReduce">-</button> </div> </div> <div class="pdfList" style="position:relative;overflow:auto;"> </div> </div> </template>
3.js代码
import PDFJS from 'pdfjs-dist'; import {getters} from '@/lib/store'; import {Dialog} from 'vant'; export default { data(){ return { pdfDataList : '', scale:100, } }, created() { PDFJS.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js'); }, mounted(){ this.getPdfList(); //在这里调用pdf的方法 }, methods:{ getPdfList(){ //这里是我用来请求后台返回给我返回base64格式的文件发的ajax请求 this.$toast.loading('加载中'); this.$axios.post(url, params) .then(res => { if(res.data){ this.getPageNum(res); var data = res.data; this.pdfDataList = data ; //接收传回来的数据 this.showPdf(); //调用生成PDF }else{ this.loading = false; Dialog.alert({ message:res.message }).then(()=>{ this.$router.go(-1); }); } this.$toast.hide(); }); }, async showPdf(){ let pdfList = document.querySelector('.pdfList') //通过querySelector选择DOM节点,使用document.getElementById()也一样 let base64 = this.pdfDataList.fileValue //获得bas464编码 let decodedBase64 = atob(base64) //使用浏览器自带的方法解码 let pdf = await PDFJS.getDocument({data: decodedBase64}) //返回一个pdf对象 let pages = pdf.numPages //声明一个pages变量等于当前pdf文件的页数 for (let i = 1; i <= pages; i++) { //循环页数 let canvas = document.createElement('canvas') ; let page = await pdf.getPage(i) //调用getPage方法传入当前循环的页数,返回一个page对象 let scale = 0.5;//缩放倍数,1表示原始大小 let width = document.body.clientWidth ;//窗口的宽度 let viewport = page.getViewport(scale); let context = canvas.getContext('2d'); //创建绘制canvas的对象 canvas.height = viewport.height; //定义canvas高和宽 canvas.width = viewport.width; let renderContext = { canvasContext: context, viewport: viewport }; await page.render(renderContext) canvas.className = 'canvas' //给canvas节点定义一个class名,这里我取名为canvas pdfList.appendChild(canvas) //插入到pdfList节点的最后 } } this.loading = false ; }, scaleAdd() { if(this.scale == 300) return ; this.scale += 10; this.$refs.pdf.$el.style.width = parseInt(this.scale) + "%"; }, scaleReduce() { this.scale += -10; this.$refs.pdf.$el.style.width = parseInt(this.scale) + "%"; } }, }
方法一真的是相当简单了,,代码都是差不多一样,具体情况根据自己的业务需求改改就行了,但是这种方式处理问题也严重,就是pdf不清晰,缩放之后更严重。当然,为啥会很模糊,我当然是不知道的了。。。
第二种方式更简单惹:使用vue的依赖PDFJS
第一步:安装依赖
npm install vue-pdf npm install pdfjs-dist //之前漏写了,一定要添加这个依赖,要不然会报错
第二步:template页面
export default { data(){ return { pdfSrc:'', scale:100, numPages:0 } }, components:{ pdf }, created() { PDFJS.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js'); }, mounted(){ this.getPdfList(); }, methods:{ getPdfList(){ //这里是我用来请求后台返回给我返回base64格式的文件发的ajax请求 this.$toast.loading('加载中'); this.$axios.post(url, params) .then(res => { if(res.data){ this.getPageNum(res); }else{ this.loading = false; Dialog.alert({ message:res.message }).then(()=>{ this.$router.go(-1); }); } this.$toast.hide(); }); }, async getPageNum(res){//这里注意一下哈,因为传过来的base64位文件流,所以肯定不知道page是多少了,当然是要先获取一下页数啦 var decodedBase64 = atob(res.data.DocumentData) var pdf = await PDFJS.getDocument({data: decodedBase64}) //返回一个pdf对象 this.numPages = pdf.numPages ; this.pdfSrc = `data:application/pdf;base64,${res.data.DocumentData}`; }, scaleAdd() { if(this.scale == 300) return ; this.scale += 10; for(var i in this.$refs.pdf){ this.$refs.pdf[i].$el.style.width = parseInt(this.scale) + "%"; } }, scaleReduce() { if (this.scale == 100) { return; } this.scale += -10; for(var i in this.$refs.pdf){ this.$refs.pdf[i].$el.style.width = parseInt(this.scale) + "%"; } } }, }
以上就是两种处理的方法,阔以看的出来,第二种方式明显代码更少一点,并且第二种,完美的保留了文件的清晰度;所以以后遇到base64位PDF展示就用第二种吧!