好的,当然可以。以下是整理成 Markdown 格式的解决方案,非常适合用于博客记录。


Java 导出包含内嵌图片的 Word 文档解决方案

本文介绍几种在 Java 中导出 Word 文档并将图片完全内嵌到文件中的可靠方案,确保文档在任何环境下打开都能正常显示图片。

核心目标

将图片数据完全写入 Word 文档的文件结构中,生成一个自包含.docx 文件,不依赖任何外部图片链接。

方案一:Apache POI (XWPF) - 推荐方案

这是最常用、最原生的 Java 方案,适用于生成标准的 .docx 格式文档。

优点

  • 免费开源
  • 控制力强
  • 生成标准格式文档
  • 社区活跃,资料丰富

Maven 依赖

<dependencies>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.4</version>
    </dependency>
</dependencies>

核心代码实现

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.IOUtils;
import java.io.*;

public class WordExportWithImage {

    public static void main(String[] args) throws Exception {
        // 1. 创建新文档
        XWPFDocument document = new XWPFDocument();

        // 2. 创建段落和文本运行
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.setText("这是一个包含内嵌图片的文档:");
        run.addCarriageReturn();

        // 3. 读取图片文件
        FileInputStream imageStream = new FileInputStream("path/to/your/image.jpg");
        byte[] imageBytes = IOUtils.toByteArray(imageStream);
        imageStream.close();

        // 4. 将图片嵌入文档
        run.addPicture(new ByteArrayInputStream(imageBytes),
                      XWPFDocument.PICTURE_TYPE_JPEG,
                      "image.jpg",
                      Units.toEMU(300),  // 宽度
                      Units.toEMU(200)); // 高度

        // 5. 保存文档
        FileOutputStream out = new FileOutputStream("output_with_image.docx");
        document.write(out);
        out.close();
        document.close();

        System.out.println("包含内嵌图片的Word文档生成成功!");
    }
}

关键技术点

  • addPicture() 方法将图片字节数据直接嵌入 .docx 文件
  • .docx 本质是 ZIP 压缩包,图片被存储在包内的 word/media/ 目录
  • 使用 Units.toEMU() 确保尺寸单位正确

方案二:模板技术 (Freemarker)

适用于格式复杂、内容动态的文档场景。

优点

  • 样式与数据分离
  • 开发效率高
  • 易于维护

实现步骤

  1. 制作模板
  • 用 Word 创建 .docx 文件并设计样式
  • 在图片位置插入占位符 {{imagePlaceholder}}
  • 另存为 XML 文件并修改模板语法
  1. Java 处理逻辑
  • 读取图片并转换为 Base64 编码
  • 使用 Freemarker 引擎渲染模板
  • 将输出的 XML 重命名为 .docx 后缀
// 简化的处理流程
String templatePath = "template.xml";
String imagePath = "path/to/image.jpg";

// 将图片转换为 Base64
byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);

// 准备数据模型
Map<String, Object> data = new HashMap<>();
data.put("imagePlaceholder", base64Image);

// 渲染模板并输出
Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
cfg.setDirectoryForTemplateLoading(new File("templates"));
Template template = cfg.getTemplate("word-template.xml");

try (Writer out = new FileWriter("output.docx")) {
    template.process(data, out);
}

方案三:Docx4j 库

功能更强大的专业级解决方案。

优点

  • 对 Word 高级特性支持更好
  • 功能丰富全面

缺点

  • 学习曲线较陡峭
  • 商业使用需注意许可证

代码示例

// 初始化
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();

// 创建段落和文本运行
org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
P p = factory.createP();
R r = factory.createR();

// 嵌入图片
FileInputStream is = new FileInputStream(new File("path/to/image.jpg"));
byte[] bytes = IOUtils.toByteArray(is);
is.close();

BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(
    wordMLPackage, bytes
);
Inline inline = imagePart.createImageInline("image.jpg", "图片描述", 1, 2, false);

// 添加到文档
r.getContent().add(factory.createDrawing(inline));
p.getContent().add(r);
wordMLPackage.getMainDocumentPart().addObject(p);

// 保存文档
wordMLPackage.save(new File("output.docx"));

方案对比

方案

易用性

灵活性

学习成本

适用场景

Apache POI

⭐⭐⭐⭐

⭐⭐⭐⭐

⭐⭐⭐

大多数常规需求

模板技术

⭐⭐⭐

⭐⭐⭐⭐⭐

⭐⭐⭐⭐

复杂格式、批量生成

Docx4j

⭐⭐

⭐⭐⭐⭐⭐

⭐⭐⭐⭐⭐

企业级复杂需求

总结

对于大多数应用场景,推荐使用 Apache POI (XWPF) 方案,因为:

  1. 完全满足图片内嵌需求
  2. 代码简洁直观,易于维护
  3. 社区支持良好,文档齐全
  4. 生成的文档兼容性最好

无论选择哪种方案,都能实现图片完全内嵌到 Word 文档中,确保文档在任何环境下都能正常显示。