最近vue项目中遇到预览pdf出现乱码问题,尝试了各种办法受尽折磨,以此记录一下使用的几种方法
**1.使用pdfjs-dist 插件,通过iframe标签显示 **
首先 npm install pdfjs-dist --save
npm直接下载插件 npm install --save pdfjs-dist@2.0.943,**@2.0.943**这是指定版本号,不需要指定版本的就不需要带,下载后在使用的页面直接引入。
然后直接设置pdf路径就可以直接展示,downloadUrl 是插件中的viewer.html地址,resFile是文件下载地址,到此就能正常预览PDF,组件功能也很多,如需要额外的功能也可以在viewer.js自行修改
2.使用vue-pdf插件
执行下面命令下载插件(vue-pdf是基于pdfjs-dist),并修改pacakge.json文件
npm i [email protected] --save
npm i [email protected] --save
"dependencies": {
"pdfjs-dist": "2.5.207",
"vue-pdf": "4.2.0",
}
在使用的页面中直接引入插件,标签为<pdf>就可以,路径赋值同第一种方法
** 3.第三种方法使用了pdfjs-dist插件,通过url实现PDF转图片显示**
引入需要的插件pdfjs-dist,workerSrc(具体功能可以百度,没搞明白)
本地文件URL:
通过URL转换blob类型,然后转为base64,这块可以直接拿去用,getDay()方法可以换成自己想要的文件名,这个方法转成base64后是包含前面类型的,又处理了一下,看个人需求
fileLinkToStreamDownload(url) { let fileName = this.getDay() let reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\/])+$/ if (!reg.test(url)) { throw new Error('传入参数不合法,不是标准的文件链接') } else { let xhr = new XMLHttpRequest() xhr.open('get', url, true) xhr.setRequestHeader('Content-Type', `application/pdf;charset-UTF-8`) xhr.responseType = 'blob' let that =this xhr.onload = function() { if (this.status == 200) { //接受二进制文件流 var blob = this.response // that.downloadExportFile(blob, fileName); that.blobToBase64(blob).then(res => { // blob转base64 let baseArr = res.split(','); that.showPdf(baseArr[1]); }) } } xhr.send() } }, //Blob类型转BASE64 blobToBase64(blob) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = (e) => { resolve(e.target.result); }; // readAsDataURL fileReader.readAsDataURL(blob); fileReader.onerror = () => { reject(new Error('blobToBase64 error')); }; }); }, getDay() { let time = new Date(), year = time.getFullYear(), month = time.getMonth() + 1, day = time.getDate(), timeStem = time.getTime() return `${year}/${month}/${day}/${timeStem}.pdf` },
拿到base64后,开始转图片处理:这个原理这里不多说了,也是照搬的, 如果PDFJS.getDocument()获取不到pdf对象,可以考虑一下版本问题(@2.2.228亲测好用)
async showPdf(base64Val) {
let pdfList = document.querySelector('.pdfList') //通过querySelector选择DOM节点,使用document.getElementById()也一样
let base64 = base64Val //获得bas464编码
let decodedBase64 = window.atob(base64) //使用浏览器自带的方法解码
let pdfCurrent = await PDFJS.getDocument({data: decodedBase64}) //返回一个pdf对象
let pages = pdfCurrent.numPages //声明一个pages变量等于当前pdf文件的页数
for (let i = 1; i <= pages; i++) { //循环页数
let canvas = document.createElement('canvas')
let page = await pdfCurrent.getPage(i) //调用getPage方法传入当前循环的页数,返回一个page对象
let scale = 1;//缩放倍数,1表示原始大小
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节点的最后
}
},
通过这个方法亲测可以成功转图片,但是依旧没解决图片乱码问题
**4.直接通过iframe标签 **
页面标签
还是通过转码,创建下载链接,直接给地址赋值皆可以了,#toolbar = 0 设置工具栏不显示
我这块需求是不能下载,只能打印,所以隐藏了工具栏,新增了打印按钮,最开始想的是直接window.print()方法打印页面,先看效果
只打印pdf界面右侧的小图(没搞懂),然后决定使用print-js打印插件,还是npm install--save *print-js 先下载插件 *
在需要的页面直接引入
用法很简单,按钮绑定
直接用就可以,直接把地址附上,type是pdf类型就可以了
到这就实现了预览,打印功能,但还没找到获取打印页面按钮的方法,有知道的可以交流。
期间还涉及到了vue父窗口,子窗口通信的问题,碰到同样问题的可以看一下,附上图片
父页面
子页面调用
地址如下
版权归原作者 今天的砖格外烫手. 所有, 如有侵权,请联系我们删除。