杰瑞科技汇

Java如何实现HTML转Word?

核心思路

无论使用哪种库,转换的核心思路通常分为两步:

Java如何实现HTML转Word?-图1
(图片来源网络,侵删)
  1. 解析 HTML:将 HTML 字符串或文件解析成一个 Java 可以操作的对象模型。
  2. 生成 Word 文档:根据解析后的内容,使用 Word 操作库(如 Apache POI)来创建 .docx 文件,并填充内容。

使用 Apache POI (纯 Java,功能强大)

这是最底层、最灵活的方式,但也是代码量最多、最复杂的方式,你需要手动处理 HTML 标签到 Word 元素的映射。

原理

  • 使用一个 HTML 解析器(如 Jsoup)来解析 HTML,提取文本、图片、表格等元素。
  • 使用 Apache POI 库来创建 Word 文档的各个部分(段落、表格、图片等)。

优点

  • 完全控制:你可以精确控制 Word 文档的每一个细节,如字体、颜色、段落样式、页眉页脚等。
  • 不依赖外部服务:所有逻辑都在本地运行,数据安全性高。
  • 功能最全:可以实现 Word 支持的所有复杂功能。

缺点

Java如何实现HTML转Word?-图2
(图片来源网络,侵删)
  • 代码复杂:需要编写大量的样板代码来构建 Word 文档结构。
  • 需要手动处理:HTML 标签(如 <div>, <span>)与 Word 元素(如 XWPFParagraph, XWPFRun)之间没有直接对应,需要你自行实现转换逻辑。

示例代码 (简化版)

这个示例只处理了文本和粗体/斜体,实际项目中需要处理更多标签。

添加 Maven 依赖

<dependencies>
    <!-- Apache POI for .docx -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    <!-- Jsoup for HTML parsing -->
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.15.3</version>
    </dependency>
</dependencies>

Java 代码

import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.FileOutputStream;
import java.io.IOException;
public class HtmlToWordPoi {
    public static void main(String[] args) {
        String htmlContent = "<h1>这是一个标题</h1>" +
                             "<p>这是一个段落,包含<b>粗体</b>和<i>斜体</i>文本。</p>" +
                             "<p>这是一个包含链接的段落:<a href=\"https://www.example.com\">示例链接</a></p>" +
                             "<table border=\"1\">" +
                                "<tr><th>Header 1</th><th>Header 2</th></tr>" +
                                "<tr><td>Cell 1</td><td>Cell 2</td></tr>" +
                             "</table>";
        String outputPath = "C:\\temp\\output_from_poi.docx";
        try {
            convertHtmlToWord(htmlContent, outputPath);
            System.out.println("Word 文档生成成功: " + outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void convertHtmlToWord(String html, String outputPath) throws IOException {
        // 1. 使用 Jsoup 解析 HTML
        Document doc = Jsoup.parse(html);
        // 2. 创建一个新的 Word 文档
        XWPFDocument document = new XWPFDocument();
        // 3. 遍历 HTML 元素并添加到 Word 文档
        for (Element element : doc.body().children()) {
            if (element.tagName().equals("h1")) {
                XWPFParagraph p = document.createParagraph();
                p.setBold(true);
                p.setFontSize(16);
                XWPFRun r = p.createRun();
                r.setText(element.text());
            } else if (element.tagName().equals("p")) {
                XWPFParagraph p = document.createParagraph();
                // 处理段落内的内联元素
                for (Node node : element.childNodes()) {
                    if (node instanceof org.jsoup.nodes.TextNode) {
                        XWPFRun r = p.createRun();
                        r.setText(((TextNode) node).text());
                    } else if (node instanceof Element) {
                        Element inlineElement = (Element) node;
                        XWPFRun r = p.createRun();
                        if (inlineElement.tagName().equals("b") || inlineElement.tagName().equals("strong")) {
                            r.setBold(true);
                        }
                        if (inlineElement.tagName().equals("i") || inlineElement.tagName().equals("em")) {
                            r.setItalic(true);
                        }
                        r.setText(inlineElement.text());
                    }
                }
            } else if (element.tagName().equals("table")) {
                XWPFTable table = document.createTable();
                // ... 处理表格行和单元格的逻辑,这里省略 ...
            }
            // ... 可以继续添加对 ul, ol, img 等标签的处理 ...
        }
        // 4. 将文档写入输出文件
        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            document.write(out);
        }
    }
}

使用 docx4j + Flying Saucer (推荐,功能与易用性平衡)

这是目前最推荐的方案之一,它结合了 Flying Saucer 的 HTML 渲染能力和 docx4j 的 Word 生成能力。

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

原理

  1. HTML 转 XHTML:Flying Saucer (xhtmlrenderer) 是一个 XHTML 渲染引擎,它能将 XHTML (一个更严格的 HTML) 渲染成一个可打印的格式,比如图片或 PDF。
  2. 使用 docx4j:docx4j 提供了一个 XHTMLImporter,它可以解析 Flying Saucer 生成的 XHTML DOM,并将其转换为 Apache POI 的 XWPFDocument 对象。

优点

  • 保留样式:能很好地保留 HTML 中的 CSS 样式(如颜色、字体、边距等),这是 POI 原生方式难以做到的。
  • 代码相对简洁:相比纯 POI,代码量大大减少,你主要关注 HTML 的编写。
  • 功能强大:支持复杂的布局、列表、表格等。

缺点

  • 依赖多:需要引入 docx4j 和 Flying Saucer 两个较大的库。
  • 性能开销:HTML 到 XHTML 的渲染过程会带来一定的性能开销。
  • 不完全兼容:不是所有的 CSS 属性都能完美映射到 Word 格式。

示例代码

添加 Maven 依赖

<dependencies>
    <!-- docx4j core -->
    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j-core</artifactId>
        <version>11.4.4</version>
    </dependency>
    <!-- docx4j for importing XHTML -->
    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j-importxhtml</artifactId>
        <version>11.4.4</version>
    </dependency>
    <!-- Flying Saucer for XHTML rendering -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf</artifactId>
        <version>9.1.22</version>
    </dependency>
    <!-- For logging, docx4j uses slf4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.36</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.36</version>
    </dependency>
</dependencies>

Java 代码

import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.P;
import org.jsoup.Jsoup;
import org.xhtmlrenderer.css.style.CascadingStyle;
import org.xhtmlrenderer.css.style.Style;
import org.xhtmlrenderer.layout.Box;
import org.xhtmlrenderer.layout.Context;
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xhtmlrenderer.util.FSImageWriter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
public class HtmlToWordDocx4j {
    public static void main(String[] args) {
        String htmlContent = "<html><head><style>body { font-family: Arial; } h1 { color: blue; }</style></head>" +
                             "<body><h1>Docx4j 示例标题</h1>" +
                             "<p>这是一个使用 <b>docx4j</b> 和 <i>Flying Saucer</i> 生成的 Word 文档。</p>" +
                             "<p style=\"color: red; font-size: 12px;\">这段文字是红色的。</p></body></html>";
        String outputPath = "C:\\temp\\output_from_docx4j.docx";
        try {
            convertHtmlToWordWithDocx4j(htmlContent, outputPath);
            System.out.println("Word 文档生成成功: " + outputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void convertHtmlToWordWithDocx4j(String html, String outputPath) throws Exception {
        // 1. 使用 Jsoup 清理和格式化 HTML,确保它是有效的 XHTML
        // 注意:Flying Saucer 需要有效的 XHTML,<br /> 而不是 <br>
        org.jsoup.nodes.Document jsoupDoc = Jsoup.parse(html);
        String xhtml = jsoupDoc.html(); // Jsoup 的 .html() 方法会输出格式化的 XHTML
        // 2. 创建一个 WordprocessingMLPackage
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
        // 3. 使用 XHTMLImporter 将 XHTML 导入到 Word 文档的主部分
        MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
        // docx4j 会自动处理大部分标签和样式
        documentPart.getContent().addAll(XHTMLImporter.convert(xhtml, null));
        // 4. 保存 Word 文档
        wordMLPackage.save(new File(outputPath));
    }
}

注意:上面的 XHTMLImporter.convert 是 docx4j 的核心,它已经封装了大部分复杂逻辑,你只需要提供格式良好的 XHTML 即可。


使用 iText (商业库,有免费版)

iText 是一个非常著名的 PDF 和 Word 操作库,它也提供了 HTML 转 Word 的功能。

原理: iText 有一个专门的 HtmlConverter 类,它可以直接将 HTML 字符串或文件转换为 com.itextpdf.html2pdf.HtmlConverter 对象,然后保存为 .docx 格式。

优点

  • API 简单:一行代码就能完成转换,非常方便。
  • 性能较好:底层实现经过优化。

缺点

  • 商业许可:iText 5 及之前的版本在 AGPL 许可下是免费的,但如果用于闭源的商业项目,需要购买商业许可证,iText 7 引入了更严格的许可条款。
  • 样式控制有限:虽然支持 CSS,但与 docx4j 相比,在 Word 特有样式的精细控制上可能稍弱。

示例代码

添加 Maven 依赖

<dependencies>
    <!-- iText 7 Core -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext7-core</artifactId>
        <version>7.2.5</version>
        <type>pom</type>
    </dependency>
    <!-- HTML to PDF/Word add-on -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>html2pdf</artifactId>
        <version>4.0.3</version>
    </dependency>
</dependencies>

Java 代码

import com.itextpdf.html2pdf.HtmlConverter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class HtmlToWordIText {
    public static void main(String[] args) {
        String htmlContent = "<h1>iText 示例标题</h1>" +
                             "<p>这是一个使用 <b>iText</b> 生成的 Word 文档。</p>";
        String outputPath = "C:\\temp\\output_from_itext.docx";
        try {
            convertHtmlToWordWithIText(htmlContent, outputPath);
            System.out.println("Word 文档生成成功: " + outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void convertHtmlToWordWithIText(String html, String outputPath) throws IOException {
        // iText 的 HtmlConverter 可以直接将 HTML 写入 .docx 文件
        // 它会自动处理基本的 HTML 标签和样式
        try (FileOutputStream fos = new FileOutputStream(new File(outputPath))) {
            HtmlConverter.convertToDocument(html, fos);
        }
    }
}

总结与对比

特性 Apache POI + Jsoup docx4j + Flying Saucer (推荐) iText
易用性 低,代码复杂 中,代码相对简洁 高,API 极简
样式保留 差,需手动实现 ,支持大部分 CSS 中,支持基本 CSS
功能丰富度 极高,可实现所有 Word 功能 高,能满足大部分需求 高,功能强大
性能 快 (纯 Java) 中,有渲染开销 较快
依赖 POI, Jsoup docx4j, Flying Saucer iText 核心库
成本 免费 (开源) 免费 (开源) 有商业许可限制
适用场景 需要极致控制、不介意写大量代码的场景 需要较好保留 HTML 样式、追求开发效率的场景 快速实现、对样式要求不高、且能接受其许可的商业项目

如何选择?

  • 新手或追求快速开发:选择 iText,如果项目是开源的或者符合其免费许可条款,这是最快的方式。
  • 需要保留 HTML 样式(如颜色、字体、边距):强烈推荐 docx4j + Flying Saucer,它在功能和易用性之间取得了最佳平衡,是目前社区的主流选择。
  • 需要精细控制 Word 文档的每一个细节(如复杂页眉页脚、图表、VBA宏等):选择 Apache POI,虽然痛苦,但它是唯一能让你完全掌控一切的方式,通常可以先尝试 docx4j,如果发现某些样式无法转换,再考虑用 POI 进行微调。
分享:
扫描分享到社交APP
上一篇
下一篇