从 HTML 模板导出 PDF 文件

简介: 学习如何使用 Thymeleaf 和 Flying Saucer PDF 库从 HTML 模板文件中导出 .pdf 文件

一、添加 Thymeleaf 和 Flying Saucer PDF 库

要在 Gradle 构建项目中使用 Thymeleaf 和 Flying Saucer PDF 库,请将以下依赖项添加到 build.gradle 文件中。

implementation group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.13.RELEASE'
implementation group: 'org.xhtmlrenderer', name: 'flying-saucer-pdf', version: '9.1.22'

要在 Maven 构建项目中使用 Thymeleaf 和 Flying Saucer PDF 库,请将以下依赖项添加到 pom.xml 文件中。

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.13.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.22</version>
</dependency>

二、实现 Exporter 类生成 PDF 文件

创建一个名为 PdfFileExporter 的新 Java 类,在该类中,我们使用 Thymeleaf 模板引擎从给定的模板文件名和方法 generateHtml() 中的数据填充 HTML 内容。然后我们实现 exportPdfFile() 方法从 HTML 内容写入 .pdf 文件。

PdfFileExporter.java

import com.lowagie.text.DocumentException;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Map;
public class PdfFileExporter {
    public void exportPdfFile(String templateFileName, Map<String, Object> data, String pdfFileName) {
        String htmlContent = generateHtml(templateFileName, data);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(pdfFileName);
            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocumentFromString(htmlContent);
            renderer.layout();
            renderer.createPDF(fileOutputStream, false);
            renderer.finishPDF();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
    private String generateHtml(String templateFileName, Map<String, Object> data) {
        TemplateEngine templateEngine = createTemplateEngine();
        Context context = new Context();
        context.setVariables(data);
        String htmlContent = templateEngine.process(templateFileName, context);
        return htmlContent;
    }
    private TemplateEngine createTemplateEngine() {
        ClassLoaderTemplateResolver pdfTemplateResolver = new ClassLoaderTemplateResolver();
        pdfTemplateResolver.setPrefix("pdf-templates/");
        pdfTemplateResolver.setSuffix(".html");
        pdfTemplateResolver.setTemplateMode("HTML5");
        pdfTemplateResolver.setCharacterEncoding("UTF-8");
        pdfTemplateResolver.setOrder(1);
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(pdfTemplateResolver);
        return templateEngine;
    }
}

三、将 HTML 模板文件添加到资源目录

例如,我们需要实现一个程序来将供应订单表格导出为 PDF 文件。

在这一步中,我们在 resources/pdf-templates 目录下创建新的 Thymeleaf 格式的 HTML 模板文件,文件名为 order-template.html,如下所示。

资源/pdf-templates/order-template.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <style>
        h1 {
            color: #25a7e7;
            text-align: center;
        }
        .order {
            width: 100%;
        }
        .order, .order th, .order td {
            border: 1px solid #25a7e7;
            border-collapse: collapse;
        }
        .order th {
            background-color: #25a7e7;
            color: white;
        }
        .total {
            text-align: right;
        }
    </style>
</head>
<body>
<table>
    <tr>
        <td>
            <img width="80" src="https://i-1-lanrentuku.52tup.com/2020/11/6/c31b2f7a-d84f-4340-b6fe-31a9271137e1.png?imageView2/2/w/1024/" />
        </td>
        <td>
            <h1>Supply Order Form</h1>
        </td>
    </tr>
</table>
<div>
    <table>
        <tr>
            <td th:text="'Date: ' + ${#dates.format(order.date, 'dd/MM/yyyy')}"></td>
        </tr>
        <tr>
            <td th:text="'Order #: ' + ${order.orderNo}"></td>
        </tr>
        <tr>
            <td th:text="'Request Date: ' + ${#dates.format(order.requestDate, 'dd/MM/yyyy')}"></td>
        </tr>
        <tr>
            <td th:text="'Order Date: ' + ${#dates.format(order.orderDate, 'dd/MM/yyyy')}"></td>
        </tr>
    </table>
</div>
<br />
<table class="order">
    <tr>
        <th>Item #</th>
        <th>Description</th>
        <th>Quantity</th>
        <th>Unit Price</th>
        <th>Total</th>
    </tr>
    <tr th:each="item, iterStat: ${orderItems}">
        <td th:text="${iterStat.index + 1}"></td>
        <td th:text="${item.description}"></td>
        <td th:text="${item.quantity}"></td>
        <td th:text="${item.unitPrice}"></td>
        <td th:text="${item.total}"></td>
    </tr>
    <tr>
        <td class="total" colspan="4"><b>Total</b></td>
        <td><b th:text="${#aggregates.sum(orderItems.{total})}"></b></td>
    </tr>
</table>
</body>
</html>

四、实现 DTO 类

为了处理上面的 HTML 模板文件,我们添加了名为 Order 和 OrderItem 的 DTO 类,如下所示。

订单.java

import java.util.Date;
public class Order {
    private String orderNo;
    private Date date;
    private Date requestDate;
    private Date orderDate;
    public String getOrderNo() {
        return orderNo;
    }
    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    public Date getRequestDate() {
        return requestDate;
    }
    public void setRequestDate(Date requestDate) {
        this.requestDate = requestDate;
    }
    public Date getOrderDate() {
        return orderDate;
    }
    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }
}

订单项.java

public class OrderItem {
    private String description;
    private Integer quantity;
    private Double unitPrice;
    private Double total;
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Integer getQuantity() {
        return quantity;
    }
    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }
    public Double getUnitPrice() {
        return unitPrice;
    }
    public void setUnitPrice(Double unitPrice) {
        this.unitPrice = unitPrice;
    }
    public Double getTotal() {
        return total;
    }
    public void setTotal(Double total) {
        this.total = total;
    }
}

五、实现主类生成PDF文件

在这一步,我们实现一个 Main 类,创建一些测试数据并使用 PdfFileExporter 类导出 PDF 文件。

主.java

import java.util.*;
public class Main {
    public static void main(String... args) {
        PdfFileExporter pdfFileExporter = new PdfFileExporter();
        Map<String, Object> data = createTestData();
        String pdfFileName = "D:\\test\\order.pdf";
        pdfFileExporter.exportPdfFile("order-template", data, pdfFileName);
    }
    private static Map<String, Object> createTestData() {
        Map<String, Object> data = new HashMap<>();
        Order order = new Order();
        order.setOrderNo("ABC-12345");
        order.setDate(new Date());
        order.setOrderDate(new Date());
        order.setRequestDate(new Date());
        data.put("order", order);
        List<OrderItem> orderItems = new ArrayList<>();
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setDescription("Test Order Item 1");
        orderItem1.setQuantity(1);
        orderItem1.setUnitPrice(100.0);
        orderItem1.setTotal(100.0);
        orderItems.add(orderItem1);
        OrderItem orderItem2 = new OrderItem();
        orderItem2.setDescription("Test Order 2");
        orderItem2.setQuantity(5);
        orderItem2.setUnitPrice(50.0);
        orderItem2.setTotal(250.0);
        orderItems.add(orderItem2);
        OrderItem orderItem3 = new OrderItem();
        orderItem3.setDescription("Test Order 3");
        orderItem3.setQuantity(2);
        orderItem3.setUnitPrice(200.0);
        orderItem3.setTotal(400.0);
        orderItems.add(orderItem3);
        data.put("orderItems", orderItems);
        return data;
    }
}

执行上面的Java 文件,PDF文件将导出到D:\test\order.pdf,然后用PDF软件打开文件,可以看到PDF文件内容如下。


相关文章
|
10月前
|
机器学习/深度学习 文字识别 Shell
高效率办公PDF批量处理:批量OCR识别PDF区域文字内容,用PDF内容批量改名或导出表格的货物运单应用案例
针对铁路货运物流单存档需求,本项目基于WPF与飞桨OCR技术,实现批量图片多区域文字识别与自动重命名。用户可自定义识别区域,系统提取关键信息(如车号、批次号)并生成规范文件名,提升档案管理效率与检索准确性,支持PDF及图像文件处理。
1374 48
|
存储 JSON API
如何将 Swagger 文档导出为 PDF 文件
你会发现自己可能需要将 Swagger 文档导出为 PDF 或文件,以便于共享和存档。在这篇博文中,我们将指导你完成将 Swagger 文档导出为 PDF 格式的过程。
【PDF提取内容改名】批量提取PDF指定区域内容重命名PDF文件,PDF自动提取内容命名的方案和详细步骤
本工具可批量提取PDF中的合同编号、日期、发票号等关键信息,支持PDF自定义区域提取并自动重命名文件,适用于合同管理、发票处理、文档归档和数据录入场景。基于iTextSharp库实现,提供完整代码示例与百度、腾讯网盘下载链接,助力高效处理PDF文档。
1632 40
|
缓存 测试技术 网络安全
05百融云策略引擎项目交付-laravel实战完整交付定义常量分文件配置-独立建立lib类处理-成功导出pdf-优雅草卓伊凡
05百融云策略引擎项目交付-laravel实战完整交付定义常量分文件配置-独立建立lib类处理-成功导出pdf-优雅草卓伊凡
221 0
05百融云策略引擎项目交付-laravel实战完整交付定义常量分文件配置-独立建立lib类处理-成功导出pdf-优雅草卓伊凡
|
编译器 Python
如何利用Python批量重命名PDF文件
本文介绍了如何使用Python提取PDF内容并用于文件重命名。通过安装Python环境、PyCharm编译器及Jupyter Notebook,结合tabula库实现PDF数据读取与处理,并提供代码示例与参考文献。
|
人工智能 算法 安全
使用CodeBuddy实现批量转换PPT、Excel、Word为PDF文件工具
通过 CodeBuddy 实现本地批量转换工具,让复杂的文档处理需求转化为 “需求描述→代码生成→一键运行” 的极简流程,真正实现 “技术为效率服务” 的目标。感兴趣的快来体验下把
1018 10
|
文字识别
【PDF提取全自动改名】如何批量提取PDF指定区域的文字内容,用内容批量给PDF命名或者导出表格,学会全自动解放双手
在生活和工作中,我们常需处理大量PDF文件,如银行单据、税收单据等。手动处理效率低下,而使用“咕嘎批量PDF多区域内容提取重命名导表格系统”可快速完成数千份文档的处理,大幅提高效率。该工具通过获取PDF各区域内容坐标,导入并处理文件,最终将信息提取至表格,并根据关键信息对PDF进行重命名,方便管理和查找。
3143 47
|
人工智能 编解码 文字识别
OCRmyPDF:16.5K Star!快速将 PDF 文件转换为可搜索、可复制的文档的命令行工具
OCRmyPDF 是一款开源命令行工具,专为将扫描的 PDF 文件转换为可搜索、可复制的文档。支持多语言、图像优化和多核处理。
1657 17
OCRmyPDF:16.5K Star!快速将 PDF 文件转换为可搜索、可复制的文档的命令行工具
|
数据采集 存储 API
Python爬虫结合API接口批量获取PDF文件
Python爬虫结合API接口批量获取PDF文件
|
机器学习/深度学习 人工智能 文字识别
Zerox:AI驱动的万能OCR工具,精准识别复杂布局并输出Markdown格式,支持PDF、DOCX、图片等多种文件格式
Zerox 是一款开源的本地化高精度OCR工具,基于GPT-4o-mini模型,支持PDF、DOCX、图片等多种格式文件,能够零样本识别复杂布局文档,输出Markdown格式结果。
1885 4
Zerox:AI驱动的万能OCR工具,精准识别复杂布局并输出Markdown格式,支持PDF、DOCX、图片等多种文件格式

热门文章

最新文章