公司有个业务需求,要求后台传pdf的base64编码给前端,前端显示到界面上,后来在网上搜索了很多关于base64转pdf的文章,都写的不是非常的详细,在实现的过程中遇到很多坑,经过一天的研究终于实现了这个功能,分享一下我在这个功能中遇到的问题和解决方法

要注明的是这里用到的核心插件是pdf.js,原理是动态生成canvas标签,然后通过pdf.js生成一个能渲染出pdf的对象,随后渲染每个canvas,并且生成的pdf是画面的形式,并没有pdf之类的控件

引入插件

这里很多博客都是使用JavaScript原生的方法引入pdf.js,例如使用script标签引入外部的js脚本,或者直接把pdf.js的源码复制到项目中,但是我尝试这些方法的时候都不是特别好用,而且引入后导致项目体积过于庞大,

随后我去github上寻找通过包管理器引入pdf.js的方法,在pdf.js的github上官方说明的是用gulp如何使用pdf.js,但是对于npm来说并没有详细说明,终于我在字里行间发现了这么一句话

To use PDF.js in a web application you can choose to use a pre-built version of the library or to build it from source. We supply pre-built versions for usage with NPM and Bower under the pdfjs-dist name. For more information and examples please refer to the wiki page on this subject.

大致的意思就是如果使用npm包管理器或者bower的话,引入构建好的版本的名字为pdfjs-dist,那么我们使用npm的方法引入这个pdfjs-dist,引入的名字就随意取名了这里我叫PDFJS

import PDFJS from 'pdfjs-dist'

使用pdfjs-dist

这里后台传给我的是一个由pdf文件名字和pdf的base64编码组成的对象的数组,我取名为pdfDataList

可以看到fileName是pdf的名字,fileVale是pdf文件的base64编码,thumbnail是pdf缩略图的base64编码这里用不到先不管,之前说到需要动态生成canvas节点(这里不会canvas也不要紧,只需要根据代码一步步做就能渲染canvas)

首先我们创建一个承载所有canvas节点的父节点,取名为pdfList

然后创建一个异步函数showPdf(不懂什么是异步函数的可以去查一下async/await,这里不用异步函数也可以使用promise.then的方法,但是async/await作为异步操作的终极方案最好还是学习一下)

async showPdf() {

}

使用querySelector选择类名为pdfList的dom节点,随后遍历后台传过来的pdfDataList数组的每一项,这里用到一个浏览器自带的atob()方法解码base64,MDN上是这么解释的:

你可以使用 window.btoa() 方法来编码一个可能在传输过程中出现问题的数据,并且在接受数据之后,使用 atob() 方法再将数据解码。

语法: var decodedData = scope.atob(encodedData);

随后调用pdf.js插件的getDocument方法,getDocument是一个promise,所以使用异步函数的话前面需要加await关键字(不使用异步函数的话在方法后面加.then((pdf)=>{.......}),这个pdf对象和我这个pdf对象是同一个,同时这里暂时也没考虑异步操作出错的情况,有要求的话可以在加个catch捕获错误)

getDocument方法的参数是一个对象,对象键名为data,值为base64解码后的值,此方法返回一个pdf对象,这个对象有几个属性,可以打印出来观察一下

这里我们先用到的是numPages属性,它指的是当前pdf文件有多少页

async showPdf() {

let pdfList = document.querySelector('.pdfList') //通过querySelector选择DOM节点,使用document.getElementById()也一样

for(let value of this.pdfDataList){ //遍历后台传过来的pdfDataList

let base64 = value.fileValue //获得bas464编码

let decodedBase64 = atob(base64) //使用浏览器自带的方法解码

let pdf = await PDFJS.getDocument({data: decodedBase64}) //返回一个pdf对象

let pages = pdf.numPages //声明一个pages变量等于当前pdf文件的页数

}

}

获取当前pdf文件的对象和当前pdf文件的所有页数后,循环遍历每个页数,执行如下操作:

1)动态创建canvas节点

2)调用pdf对象原型上的getPage()方法和getViewport()方法,依次传入当前循环的页数和canvas的缩放大小(这里不懂的可以直接复制黏贴)

3)渲染当前的canvas节点

4)调用page对象的render()方法渲染当前页,此方法也是一个promise,需要使用await关键字等到状态为resolve后再执行之后的代码

5)给显示当前页面的canvas节点一个className为canvas方便修改样式,最后把这个canvas节点插入到pdfList节点中

async showPdf() {

let pdfList = document.querySelector('.pdfList') //通过querySelector选择DOM节点,使用document.getElementById()也一样

for(let value of this.pdfDataList){ //遍历后台传过来的pdfDataList

let base64 = value.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 = 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节点的最后

}

}

}

至此页面上就会多出一个canvas节点并且显示当前pdf文件的第一页的图片,如果当前pdf文件有多页就会渲染出多个canvas节点,有多个pdf文件就会先循环外层,然后再循环内层,把每个pdf文件的每一页都生成一个canvas节点

修改样式

渲染出页面后还有个要注意的点,Vue框架会给每个组件的DOM节点生成一个自定义属性,而节点动态生成的canvas节点,并没有data-v-xxxxx这样的自定义属性

而Vue会给每个组件里面的样式添加这个自定义属性,Vue框架这样做可以防止样式的相互污染(也就是style旁边的scoped属性)

我们这里可以在这个style下面再创建一个style写入样式来达到修改canvas样式的效果,但是记得这样做你整个项目里面类名叫canvas的都会获得这个样式,需要注意

写在最后

这里使用的是动态生成canvas节点然后渲染这个节点生成的图片,然而直接使用createElement生成一个节点并且频繁操作DOM会对性能有一定的影响,如果有更好的方法欢迎留言交流,感谢观看

pdfjs转图片_Vue项目pdf(base64)转图片相关推荐

  1. Vue项目pdf(base64)转图片

    公司有个业务需求,要求后台传pdf的base64编码给前端,前端显示到界面上,后来在网上搜索了很多关于base64转pdf的文章,都写的不是非常的详细,在实现的过程中遇到很多坑,经过一天的研究终于实现 ...

  2. base64 能放数组里面么_手把手教你Vue解析pdf(base64)转图片【实践】

    作者:yeyan1996 转发链接:https://juejin.im/post/5bc97ab6e51d450e5d0b7dcb 公司有个业务需求,要求后台传pdf的base64编码给前端,前端显示 ...

  3. python 生成pdf 文字和图片_Python系列—PDF文本与图片抽取

    PDF是人们日常使用最多的跨平台文档.其是一种用独立于应用程序.硬件.操作系统的方式呈现文档的文件格式.每个PDF文件包含固定布局的平面文档的完整描述,包括文本.字形.图形及其他需要显示的信息.具有良 ...

  4. 如何将PDF扫描件转换为JPG图片格式?PDF转JPG图片教程

    如何将PDF扫描件转换为JPG图片格式?我们在工作中为了方便阅读或发送给其他人,经常会把纸质版文件扫描为PDF格式文件,但是也会出现不同情况需要其中不同的几张图的时候,可能很多人都会直接截图使用,但是 ...

  5. python pdf转图片 poppler_Python将PDF转成图片—PyMuPDF和pdf2image

    前言:在最近的测试中遇到一个与PDF相关的测试需求,其中有一个过程是将PDF转换成图片,然后对图片进行测试. 粗略的试了好几种方式,其中语言尝试了Python和Java,总体而言所找到的Python方 ...

  6. 图片如何生成pdf格式?图片怎么生成pdf格式文件?

    图片如何生成pdf格式?平时的工作中我们在处理pdf文件的时候,难免会遇到各种各样的问题.有时候我们需要把图片生成pdf.可能还有些小伙伴不知道该怎么做,图片生成pdf其实很简单,下面给大家分享一个图 ...

  7. vue 后台返回的文件流进行预览_vue项目-pdf预览和下载,后台返回文件流形式

    背景:正好最近碰到了这种需求,记录下来,方便以后查看. 后端返回的文件流数据如下图所示: 后台返回数据.png 一.pdf的预览 一开始的时候百度了很多方法,有建议用pdfJs插件的,有iframe嵌 ...

  8. html图片转成pdf,如何将图片、html等格式转成pdf(示例代码)

    const int WWidth = 600;const int HHeight = 800; List AllName = new List();string FileName = "d: ...

  9. vue点击按钮怎么跳转图片_Vue中点击按钮切换图片;

    页面效果比较差,但是有图总比没图强点 这是最开始的页面,我们看到,图中只有一个"右箭头",点击右箭头; 左箭头也有了,然后我们继续点击右箭头; 右箭头没有了,只剩下了左箭头, 以上 ...

最新文章

  1. 例5.12 输入一串字符,字符个数不超过100,且以.结束。 (信息学奥赛一本通)...
  2. 虚拟方法及抽象方法在使用上的区别
  3. Pandas简明教程:八、Pandas数据透视表
  4. 发现一个CentOS第三方源epel的仓库地址(repos.fedorapeople.org)
  5. Bash Shell学习笔记二
  6. [JavaWeb-HTTP]HTTP_请求消息_请求头请求体
  7. EasyNVR、EasyDSS二次开发之:RTMP、HLS流在web页面进行无插件播放示例Demo代码
  8. 论文浅尝 | NumNet: 一种带有数学推理的机器阅读理解模型
  9. pycharm快捷键_春节快结束了回单位途中总结下pycharm快捷键
  10. 01-windows下Elasticsearch安装
  11. 单片机是什么?51单片机和stm32有什么区别?
  12. 简析H264编码中的GOP
  13. 《杀死一只知更鸟》哪个译本好?
  14. 自己动手设计一个简单的HTML网页
  15. 搭建自己的私有云盘系统(owncloud)
  16. Ubuntu操作系统是什么?它和windows有什么区别呢?
  17. cad隐藏图层命令快捷键_Auto CAD如何隐藏全部图层,快捷键是什么?
  18. flutter-拨打电话功能
  19. Robyn MMM2.0 - Facebook Marketing Science(R)市场营销-广告投放
  20. python打包成安装包_Python打包成exe,看这一篇就够了!

热门文章

  1. foo/bar/baz/qux
  2. Java:从1循环到150,在每行打印一个值,另外在每个3的倍数行上打印出foo“,在每个5的倍数行上打印“biz“,在每个7的倍数行上打印“baz“
  3. 使用PyTorch Lightning自动训练你的深度神经网络
  4. CDB断点调试器报错:Exception at 0x7715c5af, code: 0xe06d7363
  5. Mac答疑「7」超详细mac新手教程-Mac界面篇
  6. js:简单的盒子碰撞
  7. 面试时,如何正确表现自己的实力?
  8. 谷歌浏览器不支持ocx控件
  9. ACCESS集团引领健康风潮,稀缺原料和领先科技帮助品牌在大健康产业乘风破浪
  10. Parallels Desktop 16 Mac版怎么样?Parallels Desktop 16 For Mac评估