如何做一个页面转化pdf的客户端

今天分享下如何做一个页面转化pdf的客户端,文中根据实例编码详细介绍,或许对大家的编程之路有着一定的参考空间与使用价值,需要的朋友接下来跟着云南仟龙Mark一起学习一下吧。

要求

客户录入表格,点一下储存以后,能够立即下载pdf文本文档。

处理思路

服务端转化成

思路

Google浏览器在2017年自主开发设计了Chrome Headless特性,并与之与此同时发布了 puppeteer,它能够被明白为是无页面可是还可以进行网络服务器作用特性的浏览器。

因此 我们可以在服务端运行puppeteer浏览器,开启总体目标网址,应用chrome浏览器内置的变换作用开展html到pdf的变换。

服务端转化成关键编码

最先要安装puppeteer,npm安装很有可能会错误,最好是应用cnpm淘宝镜像安装。

键入 ​​cnpm i puppeteer -S​​ 安装依靠。

建立一个js文件,只须要用puppeteer浏览器开启网址,储存pdf就可以。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

​​// html2pdf.js​​

​​const puppeteer = require(​​​​’puppeteer’​​​​);​​

​​(async ​​​​function​​​​(){​​

​​// 启动服务​​

​​const browser = await puppeteer.launch();​​

​​// 打开标签页​​

​​const page = await browser.newPage();​​

​​// 转到该地址​​

​​await page.goto(​​​​’https://koa.bootcss.com/#context’​​​​);​​

​​// html页面转pdf并保存至path​​

​​await page.pdf({path:​​​​"test.pdf"​​​​,format:​​​​’A4’​​​​})​​

​​// 关闭浏览器​​

​​await browser.close();​​

​​})();​​

然后控制台输入 ​​node html2pdf.js​​ 启动服务。

当然也可以module.export将模块方法导出,根据业务逻辑来。

缺点

无法保存表单动态数据

由于是从服务端请求页面,如果不在请求地址上保存用户输入,截出来的pdf将是页面没被填写的初始状态。

换而言之,他只能进行静态页面的转换,因为我们的需求有大量用户输入,因此pass。

客户端生成核心代码

思路

使用html2canvas,输入需要转换的dom节点,遍历转换成canvas画布
将canvas画布转成base64图片,使用jsPDF创建pdf文件,把图片插入进pdf。
缺点

失真。

我们可以很明显的发现,既然是类似于对页面截图再将截图插入pdf,页面的分辨率和配置很可能影响输出图片的质量。

同时,因为是截图,可能失去页面链接等功能。

文字截断

当canvas画布大于pdf一页大小时,输出就会出错,这时我们需要判断canvas画布是否超出A4大小,如果超出,对canvas进行分割,插入到不同的页面。

这时候问题又来了,既然是分割图片,那么很可能导致图片或者文字从一半就被截断,因为我们无法分析canvas内部item的结构。

核心代码

我们的需求没有图片和链接,所以失真的问题对我们影响不大,同时我们的表单由多个重复等长的item组成,并且这些item都非常短,不会超出一张A4纸(虽然这样不严谨,如果需要,你可以获取DOM元素宽高,根据DOM元素高度裁剪)。

所以我打算直接根据item切分canvas,每个item给一页A4纸保存。

在开始之前需要理解几个核心方法:

html2canvas

1

2

3

4

5

6

7

8

9

10

​​// DOM是要转换的DOM节点​​

​​html2canvas(DOM,{​​

​​backgroundColor:​​​​"#ffffff"​​​​,​​

​​width:width,​​

​​height:height,​​

​​scale:2,​​

​​allowTaint:​​​​true​​​​,​​

​​}).then((canvas)=>{​​

​​// canvas 是转换成功后的画布​​

​​})​​

jsPDF

1

2

3

4

5

6

7

8

9

10

​​// 创建实例​​

​​let pdf = ​​​​new​​ ​​jsPDF(​​​​’'​​​​,​​​​’pt’​​​​,​​​​’a4’​​​​);​​

​​// 将图片添加到pdf文件里​​

​​// 第一个参数是待插入的文件(base64)格式,第二个是文件格式​​

​​// 第三第四是图片左上角的坐标,最后两个是图片插入后的宽高​​

​​pdf.addImage(image,​​​​’JPEG’​​​​,10,10,height,width);​​

​​// 添加新的一页​​

​​pdf.addPage(​​http://www.qlyl1688.com/​​)​​

​​// 保存pdf文件​​

​​pdf.save()​​

canvas

1

2

3

4

5

6

​​// canvas是待剪切的图片​​

​​// sx,sy是开始裁剪的坐标​​

​​// swidth、sHeight是裁剪的宽高​​

​​// dx、dy是裁剪后图像在canvas中插入的坐标​​

​​// sWidth,sHeight是裁剪后图像在canvas中的宽高​​

​​cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);​​

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

​​/**​​

​​* @description: 表单转pdf文件​​

​​* @return: pdf​​

​​*/​​

​​onSubmit(){​​

​​// 这是我要转换的表单,里面有很多一样的表格​​

​​let form = ​​​​this​​​​.$refs.form;​​

​​// 获取元素的宽高​​

​​let width = form.getBoundingClientRect().width;​​

​​let height = form.getBoundingClientRect().height;​​

​​html2canvas(form,{​​

​​backgroundColor:​​​​"#ffffff"​​​​,​​

​​width:width,​​

​​height:height,​​

​​scale:2,​​

​​allowTaint:​​​​true​​​​,​​

​​}).then((canvas)=>{​​

​​let pdf = ​​​​new​​ ​​jsPDF(​​​​’'​​​​,​​​​’pt’​​​​,​​​​’a4’​​​​);​​

​​// 进行图片切割​​

​​let canvasList = ​​​​this​​​​.splitCanvas(canvas,​​​​this​​​​.forms.length);​​

​​// 遍历canvas列表,每页添加一张图片​​

​​canvasList.forEach((item,index)=>{​​

​​// 转换图片格式为base64​​

​​let itemImage = item.toDataURL(​​​​’image/jpeg’​​​​,1.0);​​

​​// 预留10px边距,A4纸的宽在72分辨率的显示器上是595px​​

​​pdf.addImage(itemImage,​​​​’JPEG’​​​​,10,10,575.28,575.28/item.width*item.height);​​

​​// 如果不是最后一页,则分页​​

​​index == ​​​​this​​​​.forms.length-1 ? ​​​​’'​​ ​​: pdf.addPage();​​

​​})​​

​​// 文件保存​​

​​let blob = pdf.output(​​​​’blob’​​​​);​​

​​pdf.save(​​​​’test.pdf’​​​​);​​

​​})​​

​​},​​

​​/**​​

​​* @description: 对canvas进行切割​​

​​* @param {number} num 切片数量 ​​

​​* @param {canvas} canvas ​​

​​* @return {array} canvas列表​​

​​*/​​

​​splitCanvas(canvas,num){​​

​​let height = canvas.height,width = canvas.width;​​

​​let chunkHeight = height/num;​​​​// 每个切片的高度​​

​​let chunkList = [];​​​​// 存放结果canvas​​

​​for​​​​(let i=0; i<height ; i+=chunkHeight){​​

​​// 初始化裁剪矩形框位置​​

​​let sx = 0,sy = i,sWidth = width,sHeight = chunkHeight,dx = 0, dy = 0;​​

​​// 创建一个canvas节点​​

​​let canvasItem =document.createElement(​​​​"canvas"​​​​);​​

​​// 初始化画布大小​​

​​canvasItem.height = chunkHeight;​​

​​canvasItem.width = width;​​

​​let cxt = canvasItem.getContext(​​​​"2d"​​​​);​​

​​// 将裁剪的图片放到新的canvas节点​​

​​cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);​​

​​chunkList.push(canvasItem); ​​

​​}​​

​​return​​ ​​chunkList;​​

​​},​​

最终效果

表单保存后的页面

转换成pdf的效果

在这里插入图片描述

今天的文章就分享到这啦,内容转自脚本之家,下篇文章再见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值