各种文档,文章,报表,报告等这种依靠数据生成的资料,一般用户都会提出需要导出的功能。
导出一般要求导出word,Excel和pdf,这里谈一下测试过多种html转pdf的心得。(html转word目前没发现特别好用的工具包,目前我的实现的方式是apache poi ,但是确实不太好用,样式是自己解析的,在处理附加图片的时候真心很费劲)。
html转pdf 之 itext
itext是开源的java处理pdf文件的工具包,
com.itextpdf.html2pdf.HtmlConverter;
在该包下将html转pdf的接口,但是实际测试效果不佳,和页面的显示效果出入比较大。当然它也不是这篇文章的重点。
html转pdf 之 html2canvas + jspdf
这是我探究了几种实现方式后的最佳方案(对于我是最佳,技术选择只有合不合适,没有对错)。
注:是jspdf 不是pdf.js
实现的思路如下:
- 将html转化为canvas
- 将canvas转化为图片
- 将图标添加到pdf文件中
- 输出pdf 文件
优势:
- 不经过后端,减轻了后端压力
- 转化后的pdf文件和预想效果最接近(导出默认为A4,文章样式宽高如果没有调节好,不见得就一致)
- 前端很多漂亮的报表,图例,图标等资源可以直接使用,并且效果渲染的非常好。
- 支持分页。(jspdf 支持分页,但是分页规则需要自己制定)
- 结合markdown编辑器,富文本编辑器或者freemarker模板可以更好的输出优质的pdf。
劣势:
- 兼容性,canvas对IE兼容性不是很好,这个是比较尴尬的(我目前不考虑IE低版本)
- 存在pdf文件失真的问题(最终是将图片加入到pdf文件中,图片是会失真的,解决方案就是将html转化为图片的时候做放大处理,我这里是放大了3倍)
- 在html转canvas的时候又是需要处理一下。
- 签章之类的目前无法处理。(jspdf有些方面不如itext强大的)
下面是个实例,做完后会开源所有代码(使用vue开发一个文档系统)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- <script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script> -->
<script src="js/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/echarts.min.js"></script>
<div id="capture" style="background: #FFFFAA;height: 350px;width: 600px;">
<div id="main" style="width: 400px; height: 300px;"></div>
</div>
<div id="ddddd">
<img id="imgContent" />
</div>
<script>
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line'
}]
};
myChart.setOption(option);
</script>
<script>
var w = $('#capture').width();
var h = $('#capture').height();
var type = "bmp";
console.log(w + " -------------------------- " + h);
var obj = document.getElementById('capture');;
var doc = window.document;
var width = obj.offsetWidth;
var height = obj.offsetHeight;
console.log(width + " "+ height)
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var scale = 3;
canvas.width = width * scale;
canvas.height = height * scale;
canvas.getContext("2d").scale(scale, scale);
var opts = {
scale: scale,
canvas: canvas,
logging: true,
width: width,
height: height ,
};
var doc = new jsPDF();
setTimeout(function(){
html2canvas(document.querySelector("#capture"),opts).then(_canvas => {
$imgs = document.getElementById('ddddd');
//$imgs.appendChild(Canvas2Image.convertToImage(canvas, w, h, type))
var image = _canvas.toDataURL("image/jpeg",1.0);
var scalePix = 210/w ;
var heightPdf = h * scalePix;
console.log(" ::: " + heightPdf);
doc.addImage(image, type, 5, 5, 200, heightPdf);
doc.save('hello.pdf')
document.body.appendChild(_canvas)
});
},2000)
</script>
</body>
</html>
html2canvas
github https://github.com/niklasvh/html2canvas/
官网:http://html2canvas.hertzen.com/
jspdf
github https://github.com/MrRio/jsPDF