一切福田,不離方寸,從心而覓,感無不通。

xhtmlrenderer 将html转换成pdf,完美css,带图片,手动分页,解决内容断开的问题

之前用itext7将html导出为pdf,比较方便,代码较少,而且支持base64的图片。但是itext7是收费的,所以换成了xhtmlrenderer。

xhtmlrenderer自动引入依赖包itext2.0.8,而且不能再引入其他版本的itext,因为itext2.0.8是已经被废弃的,里面的很多方法在新版本已经没有了。

itext导出pdf最重要的4个难点:

1.css样式

2.中文不显示

3.图片(itext7支持比较好,不过要收费)

4.分页时内容断开的问题(itext7不会出现这种问题,不过要收费)

一、首先引入包

只需要这个就够了,它会自动引入itext2.0.8

二、页面css样式的采集

  看过很多篇itext的文章,都没有达到想象中要求。大多是说将css路径改为绝对路径,或者将css写在页面中,这都不现实。真正的项目中,你的项目经理是不会让你这么做的。

所以我找到一个能将页面所有css采集起来的js方法。传入你的标签的id,返回一个包含该id的区域的所有css样式 ,加上html,head和body标签,组成一个html的字符串。将字符串传给后台去生成pdf。值得注意的是我加了这个字体body{font-family: SimSun;},这个字符是中文字体,后端必须与前端一致。且看后面。

 今天解决了分页的时候会断开内容的问题,解决方案就是手动分页,用js计算高度然后超过页面高度的就换页,这样就不会出现自动换页的时候内容断开了。

1.我将需要显示的元素都添加class= ‘pdf-page-range’    

2. class=’pageNext'             .pageNext{page-break-after: always;} 这个css表示下一个元素将会换页,转pdf的时候itext会自动识别。

3.在前面的基础上插入以下代码即可,需要图片转换之后执行,

注意:这个修改了网页内容,如果想保留原网页内容,自行想办法 -。-!

三、图片的支持

  项目中有很多Echarts做的图表,这个生成的图表都是canvas标签,而itext是不支持canvas标签的。所以要把图表全部换成base64的img标签。这里引入一个js。

html2canvas.js,它能将制定区域截图。请看以下。

注意:

1.html2canvas()方法返回的是Promise类型,为什么要将所有 html2canvas()方法的返回值集中起来然后使用Promise.all(canvasArray).then()方法。因为html2canvas()是异步的,你的下面的js已经处理完了,它可能还没截图完成。Promise.all(canvasArray).then()方法,会在所有截图已经完成之后执行。所以我把ajax请求放在里面。(请看代码)

2. img标签闭合的问题,img标签是自闭合标签。正常情况下,浏览器不会去识别你的img的闭合标签,即使你的img标签有</img>或<img  src=""  />,浏览器最后显示还是<img>,  所以我用一个字符串代替“/”, 后台再用“/”代替这个字符串,你也可以前端就替换。(请看代码) 

3.必须给img加上宽度和高度,不然被后台转换之后尺寸会变得很小。

 四、后台代码

   项目中引入中文字体,html字符串中也必须引入。我的字体css是     body{font-family: SimSun;}

Base64ImgReplacedElementFactory图片处理类

我的页面

 

 

导出的pdf效果,自动分页,并且分页不会强制裁剪图片区域。

from:https://www.cnblogs.com/trisolaris2018/p/10754914.html