从 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文件内容如下。


相关文章
|
28天前
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
186 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
1月前
|
JavaScript
jquery图片和pdf文件预览插件
EZView.js是一款jquery图片和pdf文件预览插件。EZView.js可以为图片和pdf格式文件生成在线预览效果。支持的文件格式有pdf、jpg、 png、jpeg、gif。
49 16
|
2月前
|
前端开发 API
前端界面生成PDF并导出下载
【10月更文挑战第21天】利用合适的第三方库,你可以在前端轻松实现界面生成 PDF 并导出下载的功能,为用户提供更方便的文档分享和保存方式。你还可以根据具体的需求进一步优化和定制生成的 PDF 文件,以满足不同的业务场景要求。
|
3月前
|
Web App开发 前端开发 搜索推荐
创建HTML文件
【10月更文挑战第14天】创建HTML文件
72 4
|
3月前
|
Java Apache Maven
将word文档转换成pdf文件方法
在Java中,将Word文档转换为PDF文件可采用多种方法:1) 使用Apache POI和iText库,适合处理基本转换需求;2) Aspose.Words for Java,提供更高级的功能和性能;3) 利用LibreOffice命令行工具,适用于需要开源解决方案的场景。每种方法都有其适用范围,可根据具体需求选择。
|
3月前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
938 1
|
3月前
|
资源调度 前端开发 JavaScript
安利一款基于canvas/svg的富文本编辑器-支持在线导出PDF、DOCX
高性能:利用Canvas和SVG进行图形和矢量图形的渲染,提供高性能的绘图能力。 可扩展性:Canvas-Editor是一个开源项目,支持通过插件机制扩展编辑器的功能,如DOCX、PDF导出、表格分页等。 丰富的文本编辑功能:支持多种文本编辑操作,如插入表格、分页、性能优化等。
424 0
|
3月前
|
JavaScript 前端开发 容器
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
326 0
|
19天前
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
90 24