当前位置: 代码网 > it编程>编程语言>Java > 基于SpringBoot实现HTML转PDF功能的常用方式

基于SpringBoot实现HTML转PDF功能的常用方式

2025年10月12日 Java 我要评论
01 引言你是否因为html转pdf发愁?又是否因为中文乱码而心烦意乱?又是否因为格式导致pdf排版错乱而苦恼?…在企业里,我们经常会遇到下载pdf报告的场景,前端展示还好,可以使用pd

01 引言

你是否因为htmlpdf发愁?又是否因为中文乱码而心烦意乱?又是否因为格式导致pdf排版错乱而苦恼?…

在企业里,我们经常会遇到下载pdf报告的场景,前端展示还好,可以使用pdf.js类似的框架处理,但是很多时候,需要服务端自己渲染数据然后,上传或者邮件发送。好好的页面,转成pdf直接错乱了,只能一点点的调试,才能完成。过程费时费力。

这不,前两天正好遇到htmlpdf的需求,调整了许久的样式才完成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依赖

这里暂时忽略htmlpdf的依赖,后面按需引入。

<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即可。

htmlpdf不需要通过浏览器渲染,需要服务端直接渲染并拿到渲染之后的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";

页面元素必须要有闭合标签,否则报错

调整

调整依然是难点。经过测试,该框架的的pdfa4纸的大小基本一致。而内容则是去除留白的长度。

经过测量: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.2openhtmltopdf本身就是基于flying saucer,所以这里就不在演示,两个同宗同源。

05 小结

每一款软件都是其特定标准,调整的顺序也不一样。无论如何,解决问题的思路是一致的。相比较io.woo.htmltopdf可能更加方便,本身就支持中文,而其他两个则需要单独配置才能支持中文。你们更喜欢哪一种呢?

以上就是基于springboot实现html转pdf功能的常用方式的详细内容,更多关于springboot实现html转pdf的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com