01 引言
你是否因为html转pdf发愁?又是否因为中文乱码而心烦意乱?又是否因为格式导致pdf排版错乱而苦恼?…
在企业里,我们经常会遇到下载pdf报告的场景,前端展示还好,可以使用pdf.js类似的框架处理,但是很多时候,需要服务端自己渲染数据然后,上传或者邮件发送。好好的页面,转成pdf直接错乱了,只能一点点的调试,才能完成。过程费时费力。
这不,前两天正好遇到html转pdf的需求,调整了许久的样式才完成pdf的完美转化。
02 框架选型
将html转化成pdf的框架有很多,小编也试了好几种,将觉得好用的分享给大家。
2.1 io.woo.htmltopdf
maven
<dependency> <groupid>io.woo</groupid> <artifactid>htmltopdf</artifactid> <version>1.0.4</version> </dependency> <!-- thanks for using https://jar-download.com -->
官网地址:https://jar-download.com

github地址:https://github.com/wooio/htmltopdf-java

2.2 openhtmltopdf
maven
<dependency>
<groupid>com.openhtmltopdf</groupid>
<artifactid>openhtmltopdf-core</artifactid>
<version>1.0.10</version>
</dependency>
<dependency>
<groupid>com.openhtmltopdf</groupid>
<artifactid>openhtmltopdf-pdfbox</artifactid>
<version>1.0.10</version>
</dependency>

github地址:https://github.com/danfickle/openhtmltopdf
2.3 flying saucer
maven
<dependency>
<groupid>org.xhtmlrenderer</groupid>
<artifactid>flying-saucer-pdf</artifactid>
<version>10.0.0</version>
</dependency>

github地址:https://github.com/flyingsaucerproject/flyingsaucer
03 springboot集成thymeleaf
3.1 maven依赖
这里暂时忽略html转pdf的依赖,后面按需引入。
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>
<!-- html 2 pdf 工具 -->
3.2 页面
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>评估报告</title>
</head>
<body>
<div class="total-container">
<div class="container" th:each="item:${list}">
<input type="hidden" th:value="${item.licensecode}" name="licensecode" />
<div class="img-container">
<img th:src="${item.image1}" />
<img th:src="${item.image2}" />
</div>
<div class="title" th:text="${item.vehiclename}"></div>
<div>
<ul>
<li>
<label>品牌:</label>
<span th:text="${item.brandname}"></span>
</li>
<li>
<label>车系:</label>
<span th:text="${item.seriesname}"></span>
</li>
<li>
<label>年款:</label>
<span th:text="${item.modelyear}"></span>
</li>
<li>
<label>上牌年月:</label>
<span th:text="${item.licenseyear}"></span>
</li>
<li>
<label>里程(公里):</label>
<span th:text="${item.displaymileage}"></span>
</li>
<li>
<label>成交日期:</label>
<span th:text="${item.dealdate}"></span>
</li>
<li style="border-bottom: none;">
<label>成交价(元):</label>
<span th:text="${item.dealprice}"></span>
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
这里描述了车辆的信息
3.3 数据渲染
@requestmapping("index")
public string index(model model) {
list<map<string, object>> list = new arraylist<>();
for (int i = 0; i < 3; i++) {
map<string, object> item = new hashmap<>();
item.put("image1", "http://img.example.com/a.jpg");
item.put("image2", "http://img.example.com/b.jp");
item.put("vehiclename", "路虎defender[卫士](进口)2023款defender130 48v[卫士 130 48v] 3.0t手自-体p400 hse");
item.put("brandname", "路虎");
item.put("seriesname", "defender[卫士]");
item.put("modelyear", "2023款");
item.put("licenseyear", sdf.format(new date()));
item.put("displaymileage", df.format(new bigdecimal("9657")));
item.put("dealdate", sdf.format(new date()));
item.put("dealprice", df.format(new bigdecimal("1000000")));
list.add(item);
}
model.addattribute("list", list);
return "index";
}
3.4 渲染效果

左右没有留白。
04 html转pdf
上面已经完成html的渲染和展示。我们只需要拿到html并通过工具,转化成pdf即可。
html转pdf不需要通过浏览器渲染,需要服务端直接渲染并拿到渲染之后的html。渲染的代码块:
map<string, object> map = new hashmap<>();
map.put("list", list);
context context = new context(locale.getdefault(), map);
string html = templateengine.process("index", context);
system.out.println(html);
4.1 io.woo.htmltopdf
核心方法:
inputstream convert = htmltopdf.create()
.object(htmltopdfobject.
forhtml(htmlcontent)
.defaultencoding("utf-8"))
.convert();
ioutils.copylarge(convert, response.getoutputstream());
效果

我们会发现转成pdf之后,左右会自动留白。现在的问题是,图片需要调整一下,调整到左右留白差不多,这个是难点。
应该怎么去调整呢?
因为生成的pdf默认都是基于a4的尺寸:21cm*29.7cm。所以我们直接将宽度设置为21cm。
.container{
width: 21cm;
/*设置边框方便查看*/
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
转成pdf之后右边距还是有较大的空隙的:

我们继续加大宽度,最终结果:宽度设置23cm比较合适。此时,就可在页面上愉快的调整图片或者其他与元素了。
4.2 openhtmltopdf
核心方法
pdfrendererbuilder builder = new pdfrendererbuilder();
builder.withhtmlcontent(htmlcontent, null);
builder.tostream(response.getoutputstream());
// 配置字体支持中文
builder.usefont(new file("c:\\windows\\fonts\\simhei.ttf"), "simhei");
builder.run();

注意事项
需要设置支持中的字体,且页面的font-family需要明确指出
font-family: "simhei";
页面元素必须要有闭合标签,否则报错

调整
调整依然是难点。经过测试,该框架的的pdf和a4纸的大小基本一致。而内容则是去除留白的长度。
经过测量:pdf长度794px,两边留白56px,所以页面长度:794-56-56 = 682px
调正页面长度:
.container{
font-family: "simhei";
width: 682px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
效果非常完美:

4.3 flying saucer
核心方法
itextrenderer renderer = new itextrenderer();
renderer.getfontresolver().addfont("c:\\windows\\fonts\\simh ei.ttf", basefont.identity_h,basefont.not_embedded);
renderer.setdocumentfromstring(htmlcontent);
renderer.layout();
renderer.createpdf(response.getoutputstream());
这里同样要设置支持中文,和openhtmltopdf配置类似。
调整方式同4.2。openhtmltopdf本身就是基于flying saucer,所以这里就不在演示,两个同宗同源。
05 小结
每一款软件都是其特定标准,调整的顺序也不一样。无论如何,解决问题的思路是一致的。相比较io.woo.htmltopdf可能更加方便,本身就支持中文,而其他两个则需要单独配置才能支持中文。你们更喜欢哪一种呢?
以上就是基于springboot实现html转pdf功能的常用方式的详细内容,更多关于springboot实现html转pdf的资料请关注代码网其它相关文章!
发表评论