杰瑞科技汇

Java如何实现HTML转Word?

核心思路

无论使用哪种库,其基本原理都是相似的:

Java如何实现HTML转Word?-图1
(图片来源网络,侵删)
  1. 解析 HTML: 读取 HTML 字符串或文件,并将其解析成一个内存中的文档对象模型。
  2. 映射样式: 将 HTML 的标签(如 <p>, <h1>, <table>)和 CSS 样式(如 font-size, color, text-align)映射到 Word 的对象模型(如段落、标题、表格、字体、颜色等)。
  3. 生成 Word: 遍历这个内存中的文档对象模型,使用 Java 的 Word 操作库来创建并填充一个 .docx 文件。

使用 Apache POI + Flying Saucer (推荐)

这是目前功能最强大、效果最接近原生 Word 的方案,它结合了两个优秀的库:

  • Apache POI: 用于创建和操作 Office 格式文件(如 .docx)的 Java API。
  • Flying Saucer (xhtmlrenderer): 一个将 XHTML/CSS 渲染成图像或文档的库,它负责将 HTML 转换成 POI 可以理解的格式。

优点:

  • 保真度高:能很好地支持 CSS 样式(如背景色、边距、字体等),生成的 Word 文档视觉效果好。
  • 功能强大:支持复杂的 HTML 结构,如表格、列表、图片(需额外处理)等。
  • 社区活跃:两个都是非常成熟和流行的项目,文档和解决方案丰富。

缺点:

  • 依赖较多:需要引入多个库,项目体积会变大。
  • 配置稍复杂:需要将两个库整合起来使用。

实现步骤

  1. 添加 Maven 依赖

    Java如何实现HTML转Word?-图2
    (图片来源网络,侵删)
    <!-- Apache POI for .docx generation -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>ooxml-schemas</artifactId>
        <version>1.4</version>
    </dependency>
    <!-- Flying Saucer for XHTML/CSS rendering -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf</artifactId>
        <version>9.1.22</version>
    </dependency>
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf-itext5</artifactId>
        <version>9.1.22</version>
    </dependency>
    <!-- 添加这个依赖以支持更完整的CSS -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-css</artifactId>
        <version>9.1.22</version>
    </dependency>
  2. 编写 Java 代码

    我们需要一个中间步骤:先将 HTML 转换成 XHTML(因为 Flying Saucer 对 XHTML 的支持更好),然后将其渲染成一个字节数组流,POI 读取这个流来创建 Word 文档。

    import org.apache.poi.xwpf.usermodel.*;
    org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    org.apache.poi.util.Units;
    org.xhtmlrenderer.swing.Java2DRenderer;
    org.xhtmlrenderer.util.FSImageWriter;
    import java.io.*;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    public class HtmlToWordConverter {
        public static void convertHtmlToWord(String htmlContent, String outputPath) throws IOException, InvalidFormatException {
            // 1. 准备 XHTML 内容 (Flying Saucer 对 XHTML 更友好)
            String xhtmlContent = convertToXhtml(htmlContent);
            // 2. 使用 Flying Saucer 将 XHTML 渲染成图片
            byte[] imageBytes = renderXhtmlToImage(xhtmlContent);
            // 3. 使用 Apache POI 创建 Word 文档并插入图片
            try (XWPFDocument document = new XWPFDocument()) {
                XWPFParagraph paragraph = document.createParagraph();
                XWPFRun run = paragraph.createRun();
                // 将字节数组输入流添加到 Word 中
                run.addPicture(new ByteArrayInputStream(imageBytes), XWPFDocument.PICTURE_TYPE_PNG, "rendered_content.png", Units.toEMU(600), Units.toEMU(800));
                // 保存 Word 文档
                try (FileOutputStream out = new FileOutputStream(outputPath)) {
                    document.write(out);
                }
                System.out.println("Word 文档生成成功: " + outputPath);
            }
        }
        private static String convertToXhtml(String htmlContent) {
            // 一个简单的转换,实际项目中可能需要更复杂的处理,如使用 Jsoup 清理 HTML
            // 确保 HTML 有正确的 DOCTYPE 和 <html>, <head>, <body> 标签
            if (!htmlContent.contains("<!DOCTYPE")) {
                htmlContent = "<!DOCTYPE html>\n" +
                        "<html>\n" +
                        "<head>\n" +
                        "    <meta charset=\"UTF-8\">\n" +
                        "    <style>\n" +
                        "        body { font-family: 'Microsoft YaHei', sans-serif; }\n" +
                        "        table { border-collapse: collapse; width: 100%; }\n" +
                        "        th, td { border: 1px solid #dddddd; text-align: left; padding: 8px; }\n" +
                        "    </style>\n" +
                        "</head>\n" +
                        "<body>\n" + htmlContent + "\n</body>\n</html>";
            }
            return htmlContent;
        }
        private static byte[] renderXhtmlToImage(String xhtmlContent) throws IOException {
            // 创建一个临时文件来存储 XHTML
            File xhtmlFile = File.createTempFile("content", ".xhtml");
            Files.write(xhtmlFile.toPath(), xhtmlContent.getBytes());
            // 使用 Flying Saucer 渲染
            Java2DRenderer renderer = new Java2DRenderer(xhtmlFile, 800); // 800 是渲染宽度
            renderer.setDocument(xhtmlFile);
            // 渲染成 BufferedImage
            java.awt.image.BufferedImage image = (java.awt.image.BufferedImage) renderer.getImage();
            // 将 BufferedImage 写入字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            FSImageWriter imageWriter = new FSImageWriter();
            imageWriter.write(image, "png", baos);
            // 删除临时文件
            Files.deleteIfExists(xhtmlFile.toPath());
            return baos.toByteArray();
        }
        public static void main(String[] args) {
            String html = "<h1 style='color: blue;'>这是一个标题</h1>" +
                          "<p>这是一个段落,<strong>包含粗体文本</strong>和<em>斜体文本</em>。</p>" +
                          "<table><tr><th>姓名</th><th>年龄</th></tr><tr><td>张三</td><td>30</td></tr></table>";
            try {
                convertHtmlToWord(html, "D:/temp/output_from_flying_saucer.docx");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

重要提示:此方案将整个 HTML 内容渲染成一张图片插入到 Word 中,这意味着 Word 中的内容是不可编辑的,如果需要生成可编辑的文本内容,则需要更复杂的解析和映射逻辑,或者考虑其他方案。


使用 iText 7 (功能强大,但商业版收费)

iText 7 是一个功能非常强大的文档操作库,它也支持 HTML 到 PDF 的转换,并且可以间接生成 Word。

Java如何实现HTML转Word?-图3
(图片来源网络,侵删)

优点:

  • 专业级:处理文档的能力非常强。
  • 支持 HTML 到 PDF:其 html2pdf 模块可以直接转换 HTML 到 PDF,效果很好。

缺点:

  • AGPL 许可证:如果你的项目是私有的,并且不遵循 AGPL 协议(即不公开你的源代码),则需要购买商业许可证,对于许多商业项目来说,这是一个重要考量。

实现步骤 (HTML to PDF)

  1. 添加 Maven 依赖

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>html2pdf</artifactId>
        <version>5.0.2</version>
    </dependency>
    <!-- 其他必要的 iText 7 依赖 -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>kernel</artifactId>
        <version>8.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>io</artifactId>
        <version>8.0.2</version>
    </dependency>
  2. 编写 Java 代码

    import com.itextpdf.html2pdf.HtmlConverter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    public class HtmlToPdfWithIText {
        public static void main(String[] args) {
            String html = "<h1>iText 7 示例</h1>" +
                          "<p>这是一个使用 iText 7 从 HTML 转换而来的 PDF。</p>";
            String outputFile = "D:/temp/output_from_itext.pdf";
            try {
                // 直接将 HTML 字符串转换为 PDF 文件
                HtmlConverter.convertToPdf(new File(outputFile), html);
                System.out.println("PDF 文件生成成功: " + outputFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

如何从 PDF 到 Word? iText 本身不直接支持 Word 生成,你可以先生成 PDF,然后使用其他库(如 Apache PDFBox + docx4j 或商业库 Aspose.Words)将 PDF 转换成 Word,但这会增加复杂性和潜在的精度损失。


使用商业库 (如 Aspose.Words)

商业库通常提供了最简单、最强大的解决方案,对格式的支持也最好。

优点:

  • API 简单易用:通常一行代码就能完成转换。
  • 保真度极高:生成的文档效果非常好,几乎与原生 Word 无异。
  • 功能全面:支持所有复杂的 Word 功能和 HTML/CSS 特性。

缺点:

  • 需要付费:需要购买许可证,对于个人项目或预算有限的项目不适用。

实现步骤 (使用 Aspose.Words)

  1. 下载 JAR 包:从 Aspose 官网下载 Aspose.Words for Java 的 JAR 包。

  2. 编写 Java 代码

    import com.aspose.words.*;
    public class HtmlToWordWithAspose {
        public static void main(String[] args) throws Exception {
            String html = "<h1 style='color: green;'>Aspose.Words 示例</h1>" +
                          "<p>这是一个使用 Aspose.Words 从 HTML 转换而来的 Word 文档。</p>" +
                          "<ul><li>列表项 1</li><li>列表项 2</li></ul>";
            // 创建一个 Document 对象
            Document doc = new Document();
            DocumentBuilder builder = new DocumentBuilder(doc);
            // 使用 InsertHtml 方法直接插入 HTML
            // 这是 Aspose.Words 最方便的地方
            builder.insertHtml(html);
            // 保存为 .docx 文件
            doc.save("D:/temp/output_from_aspose.docx");
            System.out.println("Word 文档生成成功: D:/temp/output_from_aspose.docx");
        }
    }

使用 Docx4j (纯 Java,功能尚可)

Docx4j 是一个专门用于处理 Office Open XML 格式(.docx, .xlsx, .pptx)的纯 Java 库。

优点:

  • 纯 Java:不依赖本地库。
  • 专门针对 .docx:API 设计围绕 Word 文档结构。

缺点:

  • HTML 支持:其 HTML 到 Word 的转换能力相对较弱,对 CSS 的支持有限,可能需要大量的手动调整才能达到理想效果。

实现步骤

  1. 添加 Maven 依赖

    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j-core</artifactId>
        <version>11.4.4</version>
    </dependency>
    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j-export-fo</artifactId>
        <version>11.4.4</version>
    </dependency>
  2. 编写 Java 代码 Docx4j 通常的流程是 HTML -> FO (Formatting Objects) -> Word,这个过程比较复杂,且容易出错,不推荐作为首选方案。


总结与建议

方案 优点 缺点 推荐场景
Apache POI + Flying Saucer 保真度高,功能强大,开源免费 依赖多,内容转为图片不可编辑,配置复杂 对文档视觉效果要求高,且接受内容为图片的场景(如报告、票据)
iText 7 专业级,HTML转PDF效果好 AGPL许可证(商业项目需付费) 主要需求是生成高质量PDF,且能接受许可证要求的项目
Aspose.Words API最简单,效果最好,功能最全 需要付费 预算充足,追求开发效率和最佳效果的商业项目
Docx4j 纯Java,专门针对.docx HTML支持弱,配置复杂 已在使用其生态,或对纯Java有强需求且不介意复杂性的项目

给你的建议:

  1. 如果你是个人项目、学习或开源项目:首选 Apache POI + Flying Saucer会变成图片,但它是免费且功能最强大的开源组合。
  2. 如果你的项目是商业性质,且预算充足:强烈推荐 Aspose.Words,它能为你节省大量的开发时间,并提供最完美的转换效果。
  3. 如果你的主要目标是生成 PDF,而不是 Word:可以考虑 iText 7,但要务必先了解其许可证条款。
  4. 尽量避免直接使用 Docx4j 进行 HTML 转换,除非你有非常特殊的需求和足够的时间去研究它。
分享:
扫描分享到社交APP
上一篇
下一篇