杰瑞科技汇

Java HTML如何转PDF?

下面我将为您详细介绍几种主流的实现方法,从最简单到最功能强大的,并提供详细的代码示例和优缺点分析。

Java HTML如何转PDF?-图1
(图片来源网络,侵删)

核心思路

无论使用哪个库,其基本工作流程都相似:

  1. 准备 HTML 内容:可以是一个 HTML 字符串,也可以是一个指向本地或远程 HTML 文件的 URL。
  2. 配置转换选项:设置页面大小、边距、页眉页脚、字体、图片处理等。
  3. 执行转换:调用库的 API,将 HTML 输入流转换为 PDF 输出流。
  4. 处理输出:将生成的 PDF 输出到文件、字节数组或响应流中。

使用 Flying Saucer (xhtmlrenderer) - 纯 Java 方案

这是最经典、最知名的纯 Java HTML 到 PDF 转换库,它不依赖任何浏览器或本地环境,可以在任何支持 Java 的平台上运行。

添加 Maven 依赖

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.22</version> <!-- 请使用最新版本 -->
</dependency>

核心代码示例

import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class FlyingSaucerExample {
    public static void main(String[] args) {
        // 1. 准备 HTML 内容
        String htmlContent = """
                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <style>
                        body { font-family: Arial, sans-serif; }
                        h1 { color: #333; }
                        table { border-collapse: collapse; width: 100%; }
                        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
                        th { background-color: #f2f2f2; }
                    </style>
                </head>
                <body>
                    <h1>我的第一个 PDF 报告</h1>
                    <p>这是使用 Flying Saucer 生成的 PDF 文件。</p>
                    <table>
                        <tr>
                            <th>产品</th>
                            <th>价格</th>
                        </tr>
                        <tr>
                            <td>Java 编程</td>
                            <td>¥99.00</td>
                        </tr>
                        <tr>
                            <td>Spring Boot 实战</td>
                            <td>¥129.00</td>
                        </tr>
                    </table>
                </body>
                </html>
                """;
        // 2. 创建输出文件
        File outputFile = new File("output_flying_saucer.pdf");
        try (OutputStream os = new FileOutputStream(outputFile)) {
            // 3. 创建 ITextRenderer 实例
            ITextRenderer renderer = new ITextRenderer();
            // 4. 设置 HTML 内容
            renderer.setDocumentFromString(htmlContent);
            // 5. (可选)处理相对路径的 CSS 和图片
            // renderer.setDocumentBaseURL("file:/path/to/your/resources/");
            // 6. 执行渲染
            renderer.layout();
            // 7. 生成 PDF
            renderer.createPDF(os);
            System.out.println("PDF 文件生成成功: " + outputFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优缺点分析

  • 优点:

    • 纯 Java: 无需安装浏览器,跨平台性好。
    • 开源免费: 遵循 Mozilla Public License。
    • 成熟稳定: 使用广泛,社区支持好。
    • 支持 CSS: 对 CSS 2.1 有很好的支持,支持大部分常用样式。
  • 缺点:

    Java HTML如何转PDF?-图2
    (图片来源网络,侵删)
    • CSS 支持有限: 不支持所有现代 CSS 特性(如 Flexbox, Grid, 部分 CSS3 动画)。
    • JavaScript 不支持: 无法执行页面中的 JavaScript 代码。
    • 性能: 对于非常复杂的 HTML,性能可能不如基于浏览器的方案。
    • 中文支持需要额外配置: 默认可能不支持中文字体,需要手动配置。

使用 iText 5 / iText 7 - 商业库

iText 是一个非常强大的 PDF 操作库,它也提供了 HTML 转换的功能,iText 5 是较老的版本,iText 7 是更新的版本,架构更现代化。

添加 Maven 依赖 (iText 7)

iText 7 采用模块化设计,需要引入 html2pdf 模块。

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>html2pdf</artifactId>
    <version>4.0.3</version> <!-- 请使用最新版本 -->
</dependency>

注意: iText 7 有 AGPL 许可证,如果你的项目是商业闭源项目,你需要购买商业许可证,AGPL 允许免费用于开源项目。

核心代码示例 (iText 7)

import com.itextpdf.html2pdf.HtmlConverter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class IText7Example {
    public static void main(String[] args) {
        // 1. 准备 HTML 内容 (与上面相同)
        String htmlContent = """
                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <style>
                        body { font-family: Arial, sans-serif; }
                        h1 { color: #333; }
                        table { border-collapse: collapse; width: 100%; }
                        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
                        th { background-color: #f2f2f2; }
                    </style>
                </head>
                <body>
                    <h1>使用 iText 7 生成的 PDF</h1>
                    <p>这是使用 iText 7 的 html2pdf 模块生成的 PDF 文件。</p>
                    <table>
                        <tr><th>产品</th><th>价格</th></tr>
                        <tr><td>Java 编程</td><td>¥99.00</td></tr>
                        <tr><td>Spring Boot 实战</td><td>¥129.00</td></tr>
                    </table>
                </body>
                </html>
                """;
        // 2. 创建输出文件
        File outputFile = new File("output_itext7.pdf");
        try (OutputStream os = new FileOutputStream(outputFile)) {
            // 3. 直接调用 HtmlConverter 进行转换
            HtmlConverter.convertToPdf(htmlContent, os);
            System.out.println("PDF 文件生成成功: " + outputFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优缺点分析

  • 优点:

    Java HTML如何转PDF?-图3
    (图片来源网络,侵删)
    • 功能强大: iText 本身就是业界顶级的 PDF 库,转换后可以轻松对 PDF 进行复杂操作(加密、签名、表单等)。
    • CSS 支持较好: 基于 Flying Saucer,但进行了优化和增强。
    • 文档和 API 完善: 官方文档非常详细。
  • 缺点:

    • 许可证问题: AGPL 许可证对商业项目不友好,需要付费。
    • 性能: 对于复杂页面,性能可能不是最优。

使用 wkhtmltopdf - 基于浏览器的方案

wkhtmltopdx 是一个开源命令行工具,它使用 WebKit 渲染引擎(也就是 Chrome 和 Safari 使用的核心)来将 HTML 转换成 PDF,Java 通过调用其命令行接口来使用它。

下载并安装

你需要从 wkhtmltopdf 官网 下载并安装对应你操作系统的版本,确保 wkhtmltopdf.exe (Windows) 或 wkhtmltopdf (Linux/Mac) 的路径在系统的环境变量 PATH 中,或者在 Java 代码中指定其完整路径。

添加 Java 封装库 (可选)

直接使用 Runtime.exec() 调用命令行比较繁琐,可以使用一些封装库来简化操作,com.github.jhonnymertz:java-wkhtmltopdf

<dependency>
    <groupId>com.github.jhonnymertz</groupId>
    <artifactId>java-wkhtmltopdf</artifactId>
    <version>1.1.0</version>
</dependency>

核心代码示例

import com.github.jhonnymertz.wkhtmltopdf.WkhtmltopdfExecutor;
import com.github.jhonnymertz.wkhtmltopdf.output.OutputType;
import com.github.jhonnymertz.wkhtmltopdf.parameter.Param;
import com.github.jhonnymertz.wkhtmltopdf.resource.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WkhtmltopdfExample {
    public static void main(String[] args) {
        // 1. 准备 HTML 内容
        String htmlContent = """
                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <style>
                        body { font-family: Arial, sans-serif; }
                        h1 { color: #333; }
                        table { border-collapse: collapse; width: 100%; }
                        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
                        th { background-color: #f2f2f2; }
                    </style>
                </head>
                <body>
                    <h1>使用 wkhtmltopdf 生成的 PDF</h1>
                    <p>这是使用 wkhtmltopdf 生成的 PDF 文件,它能完美支持现代 CSS。</p>
                    <table>
                        <tr><th>产品</th><th>价格</th></tr>
                        <tr><td>Vue.js 实战</td><td>¥89.00</td></tr>
                        <tr><td>React 完全指南</td><td>¥109.00</td></tr>
                    </table>
                </body>
                </html>
                """;
        // 2. 创建临时 HTML 文件
        File htmlFile = new File("temp.html");
        try (OutputStream os = new FileOutputStream(htmlFile)) {
            os.write(htmlContent.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 3. 创建输出 PDF 文件
        File outputFile = new File("output_wkhtmltopdf.pdf");
        // 4. 创建 WkhtmltopdfExecutor
        WkhtmltopdfExecutor executor = new WkhtmltopdfExecutor();
        // 5. 配置转换参数
        executor.addParam(Param.DISABLE_SMART_SHRINKING); // 禁用智能缩放
        executor.addParam(Param.NOBACKGROUND); // 不渲染背景
        executor.addParam(new Param("--orientation", "Landscape")); // 设置为横向
        // 6. 添加输入资源 (HTML文件)
        executor.addResource(new Resource(htmlFile));
        // 7. 设置输出文件
        executor.setOutputFile(outputFile);
        executor.setOutputType(OutputType.FILE);
        // 8. 执行转换
        try {
            executor.execute();
            System.out.println("PDF 文件生成成功: " + outputFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 9. 清理临时文件
            htmlFile.delete();
        }
    }
}

优缺点分析

  • 优点:

    • 极高的 CSS/JS 兼容性: 因为使用的是真实的浏览器内核,所以几乎支持所有现代 CSS 和 JavaScript 功能。
    • 渲染效果逼真: 生成的 PDF 外观与在浏览器中看到的一模一样。
    • 开源免费: 软件本身是开源的。
  • 缺点:

    • 依赖本地环境: 必须在目标服务器上安装 wkhtmltopdf,增加了部署的复杂性和服务器依赖。
    • 性能问题: 启动一个进程来转换每个请求,会消耗较多 CPU 和内存,不适合高并发场景。
    • 稳定性: 在某些服务器环境下(如无头模式、权限问题)可能会遇到问题。

如何选择?

特性 Flying Saucer (纯Java) iText 7 (商业库) wkhtmltopdf (基于浏览器)
CSS 支持 一般 (CSS 2.1) 较好 极佳 (现代 CSS)
JavaScript 支持 支持
依赖性 无 (但许可证有商业限制) 需要安装本地工具
性能 中等 中等 较差 (启动进程开销大)
易用性 简单 简单 中等 (需要配置环境)
成本 开源免费 商业项目需付费 开源免费
适用场景 简单报表、静态文档、无复杂样式 需要深度 PDF 操作(加密/签名) 需要高度还原网页样式的场景

总结建议:

  • 如果需求简单,对 CSS 要求不高,且希望部署简单:首选 Flying Saucer,它是纯 Java 解决方案,部署零烦恼。
  • 如果你的项目是开源的,或者愿意为 PDF 功能付费,并且需要后续对 PDF 进行复杂操作:可以考虑 iText 7
  • 如果你的 HTML 页面使用了非常现代的 CSS (如 Flexbox, Grid) 或 JavaScript,PDF 的视觉效果必须和网页完全一致wkhtmltopdf 是不二之选,但要接受其部署复杂性和性能开销。

对于大多数企业级应用,Flying Saucerwkhtmltopdf 是最常用的两个方案。

分享:
扫描分享到社交APP
上一篇
下一篇