SpringBoot集成:5分钟实现HTML转PDF功能

Spring Boot Freemark HTML 生成 PDF、生成水印Logo、docx文件生成PDF,Jar包运行可读取模板文件、字体文件 Spring Boot Freemark HTML 生成 PDF,Jar包运行可读取模板文件、字体文件 阅读详情

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可能更加方便,本身就支持中文,而其他两个则需要单独配置才能支持中文。你们更喜欢哪一种呢?

Spring Boot集成OpenPDF实现PDF导出功能 如果你想要在Spring Boot项目中使用OpenPDF来生成PDF文件,而不是iText,你可以通过将HTML转换成PDF的方式来实现。OpenPDF是一个开源的Java PDF库,它基于iText 5.x版本,但是它主要提供了HTML到PDF的转换能力。下面是如何在Spring Boot项目中设置并使用OpenPDF来生成PDF文件的一个简单教程。 阅读详情

相关推荐

SpringBoot实战(三十四)集成MD2File,实现Markdown转Word与HTML

本文详细介绍了如何在SpringBoot项目中集成MD2File库,实现Markdown文档到Word和HTML格式的一键转换。通过实战代码演示了从基础文件转换、字符串处理到构建完整RESTful API服务的全过程,并提供了性能优化、错误处理及企业级应用场景的拓展建议,帮助开发者快速构建高效的文档转换服务。

weixin_29218509的博客 887

spring boot 转pdf (html转pdf)

springboot html转pdf

qq_37782946的博客 2255

SpringBoot项目实战:5分钟搞定Markdown转PDF(附完整代码)

本文详细介绍了如何在SpringBoot项目中快速实现Markdown转PDF功能,使用MD2File库5分钟即可完成集成。通过完整的代码示例和实战案例,帮助开发者轻松应对技术文档、博客发布等场景的格式转换需求,提升工作效率。

weixin_30892037的博客 283

java中springboot将html网页生成PDF文件的方法分享

java中springboot将html网页生成PDF文件的方法分享

qq_25073223的博客 3942

SpringBoot项目实战:5分钟搞定knife4j接口文档美化(附完整配置代码)

本文详细介绍了如何在SpringBoot项目中快速集成knife4j美化API文档,包括基础配置、高级技巧和常见问题解决。通过5分钟配置,开发者即可获得功能强大、界面美观的接口文档,提升开发效率。

weixin_30832143的博客 386

SpringBoot项目如何用Knife4j美化Swagger3.0文档?5分钟搞定UI升级

本文详细介绍了如何在SpringBoot项目中集成Knife4j来美化Swagger3.0文档界面。通过简单的依赖配置和基础集成步骤,开发者可以快速实现API文档的UI升级,享受多主题支持、文档分类、搜索增强等核心功能。文章还涵盖了生产环境的最佳实践和常见问题解决方案,帮助开发者打造专业级的API文档。

swift5iosmith的博客 203

【推荐】15k的star,5分钟本地化部署,一款由ChatGPT开发PDF文件处理神器,功能强大,你想要的都有。

【推荐】15k的star,5分钟本地化部署,一款由ChatGPT开发PDF文件处理神器,功能强大,你想要的都有。

专注于分享最佳资源、最佳工具、有味道的技术文章 1936

3种方式对比:Spring Boot + iTextPdf高效生成PDF预览的终极方案

摘要:本文深入探讨Spring Boot与iTextPdf的高效组合实现PDF生成。内容涵盖环境搭建(强调版本兼容性与中文支持)、核心代码演示(基础文本、动态表格与PDF合并)、性能对比(纯iTextPdf最优),并附发票系统实战案例。针对中文乱码、内存溢出等常见问题提供解决方案,最后提出AI融合等扩展方向。关键结论:小数据量优先iTextPdf原生操作,复杂场景再选模板引擎,技术选型应以需求适配性为核心。(149字) 亮点提炼: 版本避坑指南与中文依赖配置 三段式代码进阶(基础→动态→合并) 性能数据对比

java专栏 1010

Spring Boot项目集成KKFileView实战:5分钟搞定在线文件预览功能(Docker Compose一键部署版)

本文详细介绍了如何在Spring Boot项目中通过Docker Compose快速集成KKFileView,实现高效在线文件预览功能。采用容器化部署方案,5分钟内即可完成Office、PDF等文件的浏览器预览功能集成,同时提供微服务调用、性能优化及安全加固等高级配置指南,助力开发者轻松应对企业级文件预览需求。

weixin_27741699的博客 428

Java后端:html转pdf实战笔记

Wkhtmltopdf可直接把浏览器中浏览的网页转换成一个pdf,他是一个把html页面转换成pdf的软件(需要安装在服务器上)。wkhtmltopdf是一个用webkit网页渲染引擎开发的用来将html转成 pdf的工具,可跟多种脚本语言进行集成来转换文档,有windows、linux等平台版本。htmltopdf 是一款基于wkhtmltopdf技术的html转pdf文档java类库,支持html转pdf和url转pdf。首先使用IDEA新建一个java空项目,可以使用maven管理依赖包。

IT技术分享社区 2607

SpringBoot集成OCR实战:从Demo到国产ARM服务器稳定部署

OCR(光学字符识别)是一种将图像中文字转换为可编辑文本的基础AI技术,其核心原理依赖于图像预处理、特征提取与模式匹配。在Java生态中,SpringBoot作为主流Web框架,常需集成Tesseract、PaddleOCR等引擎实现文档数字化,但技术价值不仅在于识别准确率,更在于跨平台兼容性、线程安全调用与生产级稳定性。典型应用场景包括票据识别、PDF结构化提取、信创环境(如RK3588 ARM服务器)下的自动化录入等。然而,真实落地常受制于JNI加载失败、tessdata路径误配、ARM架构适配缺失及O

diaoju3333的博客 371

全能数据库文档生成器:5分钟完成多格式表结构导出

**数据库文档生成**是每个开发团队都会面临的挑战,而**表结构导出**更是数据库管理中的基础需求。今天,我要为你介绍一款基于SpringBoot的开源工具——database-export,它能让你在5分钟内完成从数据库连接、表结构分析到多格式文档导出的完整流程。 ## 为什么你需要专业的数据库文档生成工具? 想象一下这样的场景:你的项目需要交接给新团队,或者需要向客户交付数据库设计文档。传

gitblog_00280的博客 453

SpringBoot+Vue财务系统:生产级凭证与报表实现

财务管理系统是企业数字化的核心基础设施,其本质是对会计准则、借贷逻辑与数据一致性的工程化落地。基于SpringBoot的Java后端保障事务原子性与BigDecimal精确计算,Vue前端通过响应式机制实现凭证表单的实时状态协同,MySQL凭借ACID特性守护账务数据的可靠性。该技术组合规避了微服务分布式事务风险、前端浮点误差、数据库非规范化等典型财务系统陷阱,广泛应用于中小企业报销审批、往来对账及资产负债表/利润表自动化生成等场景。文中深入解析凭证借贷平衡校验、科目树形管理、动态SQL报表导出等硬核模块,

weixin_33912453的博客 643

Java结合lowagie实现PDF表单动态填充与导出(免字体配置)

本文详细介绍了使用Java结合lowagie库实现PDF表单动态填充与导出的完整方案。该方案核心优势在于免字体配置,通过iTextAsian扩展包内置中文字体支持,有效解决了传统方案中文字体处理的难题。文章从模板准备、快速上手Demo、核心原理剖析到SpringBoot项目集成,提供了实战指南,并对比了iText新版等方案,为固定模板、批量生成的业务场景提供了轻量、稳定的自动化解决方案。

opencv7vision的博客 449

Qt QWebEngine实战:手把手教你将Vue3/React前端项目嵌入C++桌面程序

本文详细介绍了如何利用Qt的QWebEngine模块将Vue3/React前端项目无缝嵌入C++桌面程序,实现现代前端框架与原生C++的深度整合。通过环境准备、项目架构设计、前端适配、Qt端集成、双向通信建立及性能优化等步骤,开发者可以高效构建兼具Web灵活性和本地系统能力的混合应用。

weixin_28736355的博客 389

WSL2下用QEMU模拟ARM开发板:从编译uboot到调试全流程(附常见错误解决)

本文详细介绍了在WSL2环境下使用QEMU模拟ARM开发板的完整流程,包括uboot编译、内核调试等关键步骤。通过QEMU模拟vexpress-a9开发板,开发者可以高效搭建嵌入式开发环境,解决常见错误并提升开发效率。

solidity8miner的博客 285

SpringBoot+Vue构建汽车销售管理系统的技术实践

现代企业管理系统正加速向数字化、智能化转型,其中SpringBoot作为Java领域的主流框架,以其自动配置和快速开发特性,大幅提升了后端服务的构建效率。结合Vue.js的前端工程化能力,可实现前后端分离的高性能Web应用。在汽车销售行业,这类技术组合能有效解决库存管理、客户跟进等核心业务痛点,通过自动化流程将传统人工操作转化为实时数据流。本案例展示了如何利用SpringBoot处理高并发订单、Vue3优化前端交互,以及MySQL与Redis的数据存储方案,最终实现销售报表生成时间从2小时缩短到5分钟的显著

weixin_34205826的博客 391

DSP28335笔记——内部Flash中进行数据读写(Flash_API的使用)

Program时的报错返回值较为常见,对返回值30、31进行详解:返回值为30:每次操作写入16位的字节,直到Buffer中的数据全部写入,若写入的数据位超过16位时则返回值30。返回值为31:表示尝试将已有数据位上的0写成1。一般情况下,在Program操作之前,会将指定部分中的数据进行擦除;但擦除函数执行时间较久,且只能以扇区为单位进行擦除,因此也可以在已有数据的基础上再进行Program,但无法将已有数据的位中的0值写成1。

m0_46621336的博客 8749

SpringBoot医院药房库存管理系统:毕业设计实战与功能优化指南

库存管理系统是信息化建设的核心组成部分,它通过数据库技术对物品的入库、出库、盘点等流程进行数字化管理,其原理在于实现数据的高效增删改查与状态追踪。这类系统在提升管理效率、降低损耗、保障供应连续性方面具有重要技术价值,广泛应用于零售、物流、医疗等多个行业。在医疗场景中,药品库存管理尤为关键,涉及效期预警、供应商协同等复杂需求。本文聚焦于一个基于Java SpringBoot的医院药房药品库存管理实战项目,该项目提供了完整的源码与文档,是进行毕业设计或学习企业级开发的优质素材。文中将结合功能优化与缓存机制等热词

weixin_30911451的博客 531

偷懒必备:3种方法快速移植MFC界面资源(含.rc文件打不开解决方案)

本文针对MFC桌面应用开发,详细介绍了三种快速移植界面资源的实战方法:直接编辑.rc文件、利用Visual Studio“添加现有项”进行可视化挂载,以及双实例拖拽应急方案。文章重点剖析了.rc文件无法打开的常见问题,提供了通过修复rc.exe等关键文件来根治此问题的解决方案,帮助开发者高效复用资源,规避ID冲突等陷阱。

weixin_28358083的博客 271

Lane、PHY和Preset Value Bit

每个Lane支持不同的传输速度和带宽,例如PCIe 3.0中,一个Lane的传输速度可以达到8 GT/s(Giga Transfers per second),也就是1 GB/s(GigaBytes per second)。Preset Value Bit(预置值位)是在PCIe 3.0的Lane上新引入的一种机制,用于优化信号传输质量。PCIe设备可以包含多个Lane,例如x1、x4、x8、x16等,表示该设备同时使用的Lane数目,比如x16表示该设备采用了16个Lane,具有更高的传输速度和带宽。

weixin_58083606的博客 1295
上一篇: 分布式日志排查太头疼?TLog 让你一眼看穿请求链路!
下一篇: 除了 ${},Thymeleaf 的这些用法让你直呼内行
智_永无止境
博客等级 码龄10年 803粉丝 403原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智_永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值