核心思路
无论使用哪种库,基本思路都是相似的:

- 创建/加载 Word 文档:创建一个新文档对象,或者加载一个已有的 Word 模板。
- 获取文档的“身体”:Word 文档的内容主要存储在
Document对象的Body中。 - 创建图片对象:将本地的图片文件(如
logo.png)读取成一个库可以识别的图片对象(如XWPFPictureData)。 - 将图片添加到段落:在 Word 中,图片通常是作为一个段落元素存在的,所以你需要创建一个段落,然后将图片对象添加到这个段落中。
- 设置图片属性(可选):可以设置图片的大小、位置、环绕方式等。
- 保存文档:将操作后的
Document对象保存为一个.docx文件。
使用 Apache POI (推荐)
Apache POI 是 Java 操作 Office 文档最强大、最流行的开源库,它支持处理 .xls, .docx 等格式,对于 Word 文档,我们主要使用 POI-OOXML 模块。
优点:
- 功能全面:不仅能插入图片,还能创建复杂的表格、样式、页眉页脚等。
- 社区活跃:遇到问题容易找到解决方案。
- 行业标准:是 Java 生态中处理 Office 文档的首选。
缺点:
- API 相对复杂,学习曲线较陡峭。
- 对于简单的图片插入,代码量会多一些。
Maven 依赖
在你的 pom.xml 文件中添加以下依赖:

<dependencies>
<!-- Apache POI for Word -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version> <!-- 建议使用较新版本 -->
</dependency>
<!-- 为了支持 XWPF 相关类,还需要这个依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
代码示例:插入图片到新文档
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ApachePoiImageToWord {
public static void main(String[] args) {
// 1. 创建一个新的 XWPFDocument 对象
try (XWPFDocument document = new XWPFDocument()) {
// 2. 创建一个段落
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
// 3. 设置图片路径
String imagePath = "path/to/your/image.png"; // 替换为你的图片路径
// 4. 将图片添加到段落中
// Units 类提供了像素、英寸、厘米等单位与 EMU (English Metric Unit) 的转换
// EMU 是 Office 内部使用的单位,1 英寸 = 914400 EMU
int width = Units.toEMU(300); // 图片宽度,300像素
int height = Units.toEMU(200); // 图片高度,200像素
run.addPicture(new FileInputStream(imagePath),
XWPFDocument.PICTURE_TYPE_PNG,
"image.png",
width,
height);
// 5. 保存文档
try (FileOutputStream out = new FileOutputStream("ApachePoi_Image_Document.docx")) {
document.write(out);
}
System.out.println("图片成功插入到 Word 文档!");
} catch (IOException | InvalidFormatException e) {
e.printStackTrace();
}
}
}
代码示例:在指定位置插入图片(使用占位符)
如果需要在模板的特定位置插入图片,可以在 Word 模板中插入一个书签,然后在 Java 代码中定位到该书签。
-
创建模板
template.docx:- 在 Word 中打开一个空白文档。
- 输入一些文字,"这里是公司Logo:"。
- 在要插入图片的位置,点击
插入->链接->书签...,输入一个名字,logoBookmark,然后点击添加。 - 保存为
template.docx。
-
Java 代码:
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ApachePoiImageToBookmark {
public static void main(String[] args) {
String templatePath = "path/to/your/template.docx";
String imagePath = "path/to/your/image.png";
String outputPath = "ApachePoi_Image_To_Bookmark.docx";
try (FileInputStream fis = new FileInputStream(templatePath);
XWPFDocument document = new XWPFDocument(fis)) {
// 遍历所有段落,查找书签
for (XWPFParagraph p : document.getParagraphs()) {
for (XWPFRun r : p.getRuns()) {
// 获取 run 中的文本
String text = r.getText(0);
if (text != null && text.contains("logoBookmark")) {
// 替换书签文本为图片
r.setText("", 0); // 清空原有文本
r.addPicture(new FileInputStream(imagePath),
XWPFDocument.PICTURE_TYPE_PNG,
"logo.png",
Units.toEMU(200),
Units.toEMU(100));
}
}
}
// 保存新文档
try (FileOutputStream out = new FileOutputStream(outputPath)) {
document.write(out);
}
System.out.println("图片已根据书签成功插入!");
} catch (IOException | InvalidFormatException e) {
e.printStackTrace();
}
}
}
注意:这种方法比较简单,如果书签在表格或页眉页脚中,需要额外处理,更精确的方法是使用 document.getBookmark(bookmarkName),但 POI 对此的支持可能不如直接遍历稳定。

使用 docx4j
docx4j 是另一个功能强大的开源库,专门用于处理 Office Open XML 格式(即 .docx, .xlsx 等),它的 API 设计上比 POI 更面向对象,在某些场景下可能更直观。
优点:
- API 设计清晰,对 OOXML 结构的映射更直接。
- 功能同样非常强大,在处理复杂文档时表现优异。
缺点:
- 相比 POI,社区规模稍小。
- 许可证与 POI 不同,需要注意商业使用。
Maven 依赖
<dependencies>
<!-- docx4j core -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-core</artifactId>
<version>11.4.4</version> <!-- 建议使用较新版本 -->
</dependency>
<!-- 用于处理 OOXML -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-ooxml</artifactId>
<version>11.4.4</version>
</dependency>
</dependencies>
代码示例:插入图片到新文档
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import java.io.File;
import java.math.BigInteger;
public class Docx4jImageToWord {
public static void main(String[] args) {
try {
// 1. 创建一个新的 WordprocessingMLPackage 对象
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
// 2. 获取主文档部分
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
// 3. 创建一个段落对象
P paragraph = objectFactory.createP();
// 4. 创建一个运行对象
R run = objectFactory.createR();
// 5. 创建一个图片对象
Inline inline = objectFactory.createInline();
// 设置图片关系 ID
String imageId = documentPart.addImage(new File("path/to/your/image.png"));
// 设置图片数据
Blip blip = objectFactory.createBlip();
blip.setEmbed(imageId);
// 设置图片尺寸
// docx4j 使用 EMU 单位
long widthEmu = 1828800L; // 200像素 (200 * 914400 / 100)
long heightEmu = 1371600L; // 150像素 (150 * 914400 / 100)
// 设置图片扩展属性
Extent extent = objectFactory.createExtent();
extent.setCx(BigInteger.valueOf(widthEmu));
extent.setCy(BigInteger.valueOf(heightEmu));
// 设置图片非视觉属性
NVpr nvpr = objectFactory.createNVpr();
// 可以设置图片名称等
// 组装图片对象
inline.setBlip(blip);
inline.setExtent(extent);
inline.setNvpr(nvpr);
// 将图片对象添加到运行中
run.getContent().add(inline);
// 将运行添加到段落中
paragraph.getContent().add(run);
// 将段落添加到文档中
documentPart.getContent().add(paragraph);
// 6. 保存文档
wordMLPackage.save(new File("Docx4j_Image_Document.docx"));
System.out.println("docx4j 图片插入成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
// 为了方便,创建一个 ObjectFactory 实例
private static final ObjectFactory objectFactory = new ObjectFactory();
}
注意:docx4j 的代码看起来更冗长,因为它直接构建了 XML 结构,但这也意味着你对文档结构的控制力更强。
使用 iText (商业/AGPL 许可)
iText 是一个非常著名的 PDF 库,但它也提供了处理 Word 文档(.docx)的功能,即 iText 7 for Office。
优点:
- 如果你的项目已经在使用 iText 7,可以无缝集成。
- API 现代化,基于
PdfPCell等概念。
缺点:
- 许可证问题:iText 7 的 AGPL v3 许可证对于闭源的商业项目是“有毒”的,如果你修改了 iText 的源代码,你的项目也必须开源,商业使用需要购买商业许可证,这是选择它时最大的考量点。
Maven 依赖
<dependencies>
<!-- iText 7 Core -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.5</version> <!-- 建议使用较新版本 -->
<type>pom</type>
</dependency>
<!-- iText 7 for Office -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-7</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies>
代码示例:插入图片到新文档
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.tool.xmlpipeline.html.HtmlPipelineContext;
import com.itextpdf.tool.xml.pipeline.html.AbstractTagProcessorFactory;
import com.itextpdf.tool.xml.pipeline.end.PdfPipeline;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.StyleSheet;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ITextImageToWord {
public static void main(String[] args) {
String dest = "iText_Image_Document.docx";
String imgPath = "path/to/your/image.png";
try {
// iText 7 for Word 的处理方式与 PDF 略有不同
// 通常需要先构建一个 HTML 字符串,然后转换
// 这是一个简化的示例
// 创建一个 Document 对象
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// 加载图片
ImageData data = ImageDataFactory.create(imgPath);
Image img = new Image(data);
// 设置图片大小
img.scaleToFit(300, 200); // 按比例缩放,最大宽度300,最大高度200
// 将图片添加到文档
doc.add(img);
// 关闭文档
doc.close();
System.out.println("iText 图片插入成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:上面的例子实际上生成了 PDF,对于真正的 .docx 文件,iText 7 的处理方式更复杂,通常涉及使用 HtmlConverter 将 HTML 内容转换为 Word,或者直接操作其底层的 docx 库,对于纯图片插入,POI 和 docx4j 更直接。
总结与对比
| 特性 | Apache POI | docx4j | iText 7 |
|---|---|---|---|
| 许可证 | Apache 2.0 (宽松) | LGPL v2.1 (较宽松) | AGPL v3 (严格) |
| 易用性 | 中等,API 较老但文档多 | 中等,API 更面向对象 | 高 (如果你熟悉 iText) |
| 功能 | 非常全面 | 非常全面 | 强大,但侧重 PDF |
| 社区 | 非常活跃 | 活跃 | 活跃 |
| 推荐场景 | 首选方案,几乎所有 Java 处理 Office 的场景。 | POI 的一个优秀替代品,尤其在需要精细控制 XML 结构时。 | 如果项目已深度使用 iText,且不介意许可证问题。 |
最终建议
对于绝大多数 Java 项目,强烈推荐使用 Apache POI,它拥有最广泛的社区支持、最丰富的功能集和最灵活的许可证,虽然它的 API 可能不是最现代的,但它的稳定性和可靠性已经经过了长时间的考验。
如果你的项目对许可证有特殊要求,或者你对 POI 的 API 不太满意,docx4j 是一个非常棒的备选方案。
请根据你的项目需求、技术栈和许可证政策来选择最适合你的工具。
