Apache POI + iText (最常用)
这是最经典和广泛使用的组合,POI 负责读取和解析 Word 文档,iText 负责根据 Word 的内容生成 PDF 文件。
核心原理
- Apache POI: 用于操作 Microsoft Office 格式文件,它能够读取 Word 文档中的文本、段落、表格、图片等元素。
- iText: 用于生成 PDF 文档,你需要在代码中手动使用 POI 解析出的内容,然后用 iText 的 API 重新在 PDF 页面上“绘制”这些内容(如文本、表格、图片等)。
依赖配置
在你的 pom.xml 文件中添加以下依赖:
<!-- Apache POI for .docx -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- iText for PDF generation -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- Optional: For advanced PDF features like HTML -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
代码示例 (仅处理简单文本)
这个例子非常基础,仅用于演示核心逻辑,对于复杂的格式(如页眉页脚、页码、复杂样式),你需要编写大量的代码来处理。
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileOutputStream;
import java.io.IOException;
public class PoiAndITextConverter {
public static void main(String[] args) {
// 输入和输出文件路径
String wordPath = "input.docx";
String pdfPath = "output.pdf";
try {
// 1. 使用 POI 加载 Word 文档
XWPFDocument document = new XWPFDocument(new java.io.FileInputStream(wordPath));
// 2. 使用 iText 创建 PDF 文档
Document pdfDoc = new Document();
PdfWriter.getInstance(pdfDoc, new FileOutputStream(pdfPath));
pdfDoc.open();
// 3. 遍历 Word 文档中的段落
for (XWPFParagraph paragraph : document.getParagraphs()) {
// 获取段落文本
String text = paragraph.getText();
if (text == null || text.trim().isEmpty()) {
continue;
}
// 创建 PDF 段落
Paragraph pdfParagraph = new Paragraph();
// 设置字体 (为了支持中文,需要加载中文字体)
// 这里使用系统默认字体,实际项目中应指定具体字体文件
Font font = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.NORMAL);
pdfParagraph.add(new Chunk(text, font));
// 设置段落间距
pdfParagraph.setSpacingAfter(10f);
// 将段落添加到 PDF 文档
pdfDoc.add(pdfParagraph);
}
// 4. 遍历 Word 文档中的表格
for (XWPFTable table : document.getTables()) {
PdfPTable pdfTable = new PdfPTable(table.getNumberOfColumns());
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
PdfPCell pdfCell = new PdfPCell(new Paragraph(cell.getText()));
pdfTable.addCell(pdfCell);
}
}
pdfDoc.add(pdfTable);
}
// 5. 关闭文档
pdfDoc.close();
document.close();
System.out.println("Word 转 PDF 成功!");
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
}
}
优缺点
- 优点:
- 免费开源: 完全免费。
- 功能强大: POI 和 iText 都是功能非常成熟的库。
- 灵活性极高: 你可以精确控制 PDF 的每一个细节,实现高度定制化的转换。
- 缺点:
- 开发复杂: 工作量巨大,你需要手动处理 Word 中的每一种元素(字体、颜色、样式、图片位置、页眉页脚、页码、超链接等),并使用 iText 重新实现,对于复杂的 Word 模板,这几乎是一个噩梦。
- 样式还原困难: 很难 100% 还原 Word 中的原始样式,尤其是复杂的排版。
使用商业库 (推荐用于生产环境)
如果项目对转换质量、性能和开发效率有较高要求,使用商业库是最佳选择,它们内部封装了复杂的逻辑,通常只需要几行代码就能实现高质量的转换。
推荐库:Aspose.Words
Aspose.Words 是业界公认的最佳 Word 操作库之一,其转换效果非常出色,能高度还原原始样式。
依赖配置
Aspose.Words 是商业库,需要购买许可证,但提供有免费试用版(会有水印)。
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>23.8</version> <!-- 请使用最新版本 -->
</dependency>
代码示例 (极其简单)
import com.aspose.words.*;
public class AsposeWordsConverter {
public static void main(String[] args) throws Exception {
// 输入和输出文件路径
String wordPath = "input.docx";
String pdfPath = "output_aspose.pdf";
// 1. 加载 Word 文档
Document doc = new Document(wordPath);
// 2. 直接保存为 PDF 格式
// Aspose.Words 会自动处理所有格式转换
doc.save(pdfPath, SaveFormat.PDF);
System.out.println("Aspose.Words 转 PDF 成功!");
}
}
优缺点
- 优点:
- 极其简单: 代码量极少,通常只需 3-5 行。
- 转换质量高: 能完美还原 Word 中的几乎所有格式,包括字体、样式、表格、图片、页眉页脚、水印等。
- 性能稳定: 经过长期优化,性能和稳定性都很好。
- 功能丰富: 除了转 PDF,还支持转 HTML, EPUB, 图片等多种格式。
- 缺点:
- 收费: 需要购买商业许可证,成本较高(但对于企业项目来说,节省的开发时间和维护成本通常是值得的)。
- 有试用版限制: 免费试用版会在生成的 PDF 中添加水印。
使用 OpenOffice/LibreOffice 的命令行接口
这是一种“曲线救国”的方法,利用 OpenOffice 或 LibreOffice 自带的强大转换功能。
原理
- Java 代码通过进程调用的方式,启动 LibreOffice 的
soffice命令行程序。 soffice程序可以后台静默地将 Word 文件转换为 PDF。- Java 代码等待转换完成后,读取生成的 PDF 文件。
前提条件
- 机器上必须安装 LibreOffice (推荐,免费开源) 或 OpenOffice。
- 需要知道
soffice或soffice.exe的安装路径。
Java 代码示例
import java.io.File;
public class LibreOfficeConverter {
public static void main(String[] args) {
// LibreOffice 的安装路径 (请根据你的实际情况修改)
String libreOfficePath = "C:\\Program Files\\LibreOffice\\program\\soffice.exe";
// 输入 Word 文件路径
String inputWordPath = "input.docx";
// 输出 PDF 文件路径
String outputPdfPath = "output_libre.pdf";
// 构建命令
String[] cmd = {
libreOfficePath,
"--headless", // 无界面模式
"--convert-to", "pdf",
"--outdir", new File(outputPdfPath).getParent(), // 指定输出目录
inputWordPath
};
try {
System.out.println("开始转换...");
Process process = Runtime.getRuntime().exec(cmd);
// 等待进程结束
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("转换成功!PDF 文件已生成在: " + outputPdfPath);
} else {
System.err.println("转换失败,退出码: " + exitCode);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
优缺点
- 优点:
- 转换质量高: 因为是调用专业的 Office 软件,转换效果非常好,样式还原度高。
- 免费: LibreOffice 完全免费开源。
- 缺点:
- 依赖外部软件: 需要在服务器或客户端安装 LibreOffice,增加了部署的复杂性。
- 性能较低: 每次转换都需要启动一个新进程,比纯 Java 库慢,不适合高并发的场景。
- 平台相关: 命令在不同操作系统(Windows, Linux, macOS)下可能不同。
总结与选型建议
| 方案 | 易用性 | 转换质量 | 成本 | 适用场景 |
|---|---|---|---|---|
| POI + iText | 极低 (开发复杂) | 一般 (需大量工作) | 免费 | 学习、研究、对格式要求极简单的内部工具。不推荐用于生产项目。 |
| Aspose.Words | 极高 (非常简单) | 极高 (完美还原) | 收费 (但有试用版) | 强烈推荐用于生产环境,对质量、效率、成本有要求的企业级应用。 |
| LibreOffice CLI | 中等 | 极高 | 免费 | 无法安装商业库,且对性能要求不高的场景,需要额外维护 Office 环境。 |
最终建议:
- 如果你的项目是商业性质,预算充足,并且追求高质量的转换和开发效率:毫不犹豫地选择 Aspose.Words,它能为你节省大量的开发和维护时间。
- 如果你的项目是个人学习、内部工具,或者对格式要求不高:可以考虑 POI + iText,但一定要有心理准备,这是一个“大坑”。
- 如果你的服务器环境允许安装软件,且并发量不大:LibreOffice CLI 是一个不错的免费替代方案。
