宝哥软件园

Vue项目pdf(base64)转图片的问题及解决方案

编辑:宝哥软件园 来源:互联网 时间:2021-08-29

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

需要注意的是,这里使用的核心插件是pdf.js,原理是动态生成画布标签,然后生成一个可以通过pdf.js渲染pdf的对象,然后对每个画布进行渲染,生成的pdf是图片的形式,没有pdf这样的控件。

引入插件

这里很多博客都是使用JavaScript原生方法来引入pdf.js,比如使用脚本标签引入外部js脚本,或者直接将pdf.js的源代码复制到项目中。但是,当我尝试这些方法时,它们并不是特别容易使用,而且引入后项目太大。

然后去github想办法通过包管理器介绍pdf.js。在pdf.js的github中,官方解释了如何使用带有大口的pdf.js,但没有详细解释npm。终于,我在字里行间发现了这样一句话。

要在web应用程序中使用PDF.js,您可以选择使用预构建版本的库或从源代码构建它。我们提供NPM和鲍尔在distname下使用的预建版本。更多的信息和例子请参考关于这个主题的网页。

一般的意思是如果你用npm包管理器或者bower,引入的名字是pdfjs-dist,那么我们用npm的方法引入这个PDFJS-dist,引入的名字在这里是随机命名的。我叫pdfjs

使用pdfjs-dist从“pdfjs-dist”导入PDFJS

在后台传递给我的是一个由pdf文件名和pdf base64编码组成的对象数组。我把它命名为pdfDataList

可以看到,fileName是pdf的名称,fileVale是pdf文件的base64代码,缩略图是pdf缩略图的base64代码。你不需要把它单独留在这里。如前所述,需要动态生成canvas节点(这里没有canvas没关系,只需要根据代码一步一步渲染canvas即可)

1.首先,我们创建一个承载所有画布节点的父节点,并将其命名为pdfList

2.然后创建一个异步函数showPdf(如果不知道什么是异步函数,可以查async/await。您可以使用promise.then方法而不使用异步函数,但是最好学习async/await作为异步操作的最终解决方案)

Async showPdf() {}使用querySelector选择类名为pdfList的dom节点,然后遍历后台传输的pdfDataList数组的每一项。这里,浏览器自己的atob()方法用于解码base64,在MDN上解释为:

您可以使用window.btoa()方法对传输过程中可能出现问题的数据进行编码,然后在收到数据后使用atob()方法对数据进行解码。

语法: var解码数据=作用域。atob(编码数据);

然后调用pdf.js插件的getDocument方法,getDocument是一个承诺,所以如果使用异步函数,就需要在它之前添加await关键字(如果不使用异步函数,就添加。然后((pdf)=}.})方法之后,这个pdf对象和我的pdf对象是一样的,同时这里暂时不考虑异步操作错误,需要的话可以添加一个catch来catch错误)

getDocument方法的参数是一个对象,其键名是数据,其值是base64解码的值。此方法返回一个pdf对象,该对象有多个属性,可以打印出来进行观察

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

async show pdf(){让pdf list=document.querySelector('。pdf列表')//通过queryselector选择DOM节点。与document.getElementById()相同,用于(let值this . pdfdatalist){//traverse pdfdatalist letbase64=value.filevalue//Get base464编码let decoded base64=atob(base64)//使用浏览器自己的方法解码let pdf=await pdf js . getdocument({ data : decoded base64 })//返回一个pdf对象let pages=pdf.numpages //声明pages变量等于当前pdf文件的页数}

1)动态创建画布节点;2)在pdf对象原型上调用getPage()方法和getViewport()方法,依次传入当前循环的页数和画布的缩放大小(如果这里不懂,可以直接复制粘贴);3)渲染当前画布节点;4)调用page对象的render()方法来呈现当前页面,这也是一个承诺。在执行下面的代码之前,您需要使用await关键字等待状态被解决。5)给显示当前页面的画布节点一个画布的类名来修改样式,最后将这个画布节点插入到pdfList节点中

async show pdf(){让pdf list=document.querySelector('。pdf列表')//通过queryselector选择DOM节点。与document.getElementById()相同,用于(let值this . pdf catalist){//traverse pdf catalist letbase64=value.filevalue//Get base 464编码let decoded base64=atob(base64)//使用浏览器自己的方法解码let pdf=wait pdf js . getdocument({ data : decoded base64 })//返回一个pdf对象let pages=pdf.numPages //声明pages变量等于当前pdf文件的页数(用于i=页数;I) {//循环页数let canvas=document . create element(' canvas ')let page=await pdf . getPage(I)//调用getpage方法传入循环页数并返回一个page对象让scale=1;//缩放倍数,1表示原始大小let viewport=page.getviewport(缩放);let context=canvas . getcontext(' 2d ');//创建canvas . height=viewport . height;//定义画布高度和宽度canvas . width=viewport . width;让renderContext={ canvascontext : context,viewport : viewport };await page . render context(render context)canvas . class name=' canvas '/为canvas节点定义一个类名。在这里,我将其命名为画布pdfList。AppendChild(canvas)//插入到pdf List节点的末尾}}}此时,页面上会多一个canvas节点,显示当前pdf文件第一页的图片。如果当前pdf文件有多个页面,将呈现多个画布节点。如果有多个pdf文件,首先回收外层,然后回收内层,每个PDF文件的每一页都会生成一个画布节点。

修改样式

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

更多资讯
游戏推荐
更多+