方法概览
| 方法 | 核心库 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Apache POI + iText | Apache POI, iText | 开源免费,功能强大,对文档格式控制精细 | 实现复杂,需要手动处理样式、布局,转换效果可能不完美 | 需要深度定制,且对100%还原原格式要求不高的场景 |
| docx4j | docx4j | 专门处理 Office Open XML 格式,API 相对友好 | 转换 PDF 需要额外依赖(如 Flying Saucer),效果可能不稳定 | 需要 Java 操控 .docx/.xlsx/.pptx 内容的场景 |
| Aspose.Words | Aspose.Words | 效果最好,转换质量高,API 功能强大 | 商业收费,价格较贵,有免费试用版 | 对转换质量有高要求,且项目预算充足的企业级应用 |
| Spire.Doc | Spire.Doc | 转换效果较好,API 简单易用 | 商业收费,有免费版但有页数和功能限制 | 中小型项目,寻求简单易用的商业解决方案 |
强烈推荐:对于大多数生产环境,Aspose.Words 是最佳选择,因为它能最大程度地保留 Word 的原始格式,如果预算有限,可以优先考虑 docx4j 或 Apache POI + iText 的组合,但需要投入更多精力处理细节。
使用 Aspose.Words (推荐)
这是目前市场上公认的在 Java 中转换 Word 到 PDF 效果最好的商业库。
添加 Maven 依赖
在你的 pom.xml 文件中添加 Aspose.Words 的依赖。
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>23.8</version> <!-- 请使用最新版本 -->
</dependency>
注意:这是一个商业库,你需要从 Aspose 官网 购买许可证并激活它,否则转换后的 PDF 会有水印,在试用模式下,功能是完整的,但每页会有一个评估水印。
添加许可证 (重要)
为了避免水印,你需要加载你的许可证文件,最好的做法是在应用程序启动时加载一次。
创建一个 LicenseHelper.java 工具类:
import com.aspose.words.License;
import java.io.InputStream;
public class LicenseHelper {
public static void setLicense() {
try (InputStream is = LicenseHelper.class.getClassLoader().getResourceAsStream("Aspose.Words.lic")) {
if (is != null) {
License license = new License();
license.setLicense(is);
System.out.println("Aspose.Words License loaded successfully.");
} else {
System.out.println("License file not found. Using evaluation mode.");
}
} catch (Exception e) {
System.out.println("Error loading Aspose.Words License: " + e.getMessage());
// 继续在试用模式下运行
}
}
}
将你的 Aspose.Words.lic 文件放在 src/main/resources 目录下。
编写转换代码
转换过程非常简单,只需几行代码。
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class AsposeWordToPdfConverter {
public static void main(String[] args) {
// 1. 加载许可证 (推荐)
LicenseHelper.setLicense();
// 2. 定义输入和输出文件路径
String inputPath = "input.docx"; // 放在项目根目录或指定完整路径
String outputPath = "output_aspose.pdf";
try {
// 3. 加载 Word 文档
// 使用 FileInputStream 加载本地文件
Document doc = new Document(new FileInputStream(inputPath));
// 4. 保存为 PDF
// 使用 FileOutputStream 输出到本地文件
doc.save(outputPath, SaveFormat.PDF);
System.out.println("Word 文档已成功转换为 PDF,文件路径: " + new File(outputPath).getAbsolutePath());
} catch (Exception e) {
System.err.println("转换过程中发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
优点
- 保真度高:能完美保留 Word 中的字体、图片、表格、页眉页脚、页码、分栏等复杂格式。
- API 强大:除了转换,还可以进行文档的创建、修改、合并、拆分等复杂操作。
- 稳定可靠:商业库,有完善的技术支持。
使用 docx4j (开源免费)
docx4j 是一个专门用于处理 Office Open XML 格式(.docx, .xlsx, .pptx)的开源 Java 库,它本身不直接生成 PDF,但可以调用 Flying Saucer (xhtmlrenderer) 来实现。
添加 Maven 依赖
<dependencies>
<!-- docx4j core -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-core</artifactId>
<version>11.4.4</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 用于转换到 Flying Saucer -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>11.4.4</version>
</dependency>
<!-- Flying Saucer itself -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
</dependency>
</dependencies>
编写转换代码
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFont;
import org.docx4j.fonts.PhysicalFonts;
import java.io.File;
public class Docx4jWordToPdfConverter {
public static void main(String[] args) {
String inputPath = "input.docx";
String outputPath = "output_docx4j.pdf";
try {
// 1. 加载 Word 文档
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(inputPath));
// 2. 设置字体映射 (非常重要,否则中文等字体可能无法显示)
Mapper fontMapper = new IdentityPlusMapper();
// 添加一个系统字体,"SimSun" (宋体)
// 你需要确保系统中安装了这些字体,或者提供字体文件路径
PhysicalFont font = PhysicalFonts.get("SimSun");
if (font == null) {
System.out.println("警告: 未找到 SimSun 字体,转换后中文可能显示异常。");
} else {
fontMapper.getFontMappings().put("SimSun", font);
}
wordMLPackage.setFontMapper(fontMapper);
// 3. 将 Word 内容转换为 XHTML
XHTMLImporterImpl xhtmlImporter = new XHTMLImporterImpl(wordMLPackage);
org.w3c.dom.Document xhtml = xhtmlImporter.convert(wordMLPackage.getMainDocumentPart());
// 4. 使用 Flying Saucer 将 XHTML 渲染为 PDF
// Docx4J 的这个方法会自动处理转换过程
Docx4J.toPDF(wordMLPackage, new File(outputPath));
System.out.println("Word 文档已成功转换为 PDF,文件路径: " + new File(outputPath).getAbsolutePath());
} catch (Exception e) {
System.err.println("转换过程中发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
优点
- 开源免费:没有版权和费用问题。
- 专注 OOXML:对 Word 文档的结构有很好的理解。
缺点
- 依赖链复杂:依赖多个库,版本兼容性需要小心。
- 字体处理麻烦:需要手动配置字体映射,否则容易出现乱码或字体替换问题。
- 转换效果不稳定:对于非常复杂的 Word 布局(如复杂的页眉页脚、图文混排),转换结果可能不如 Aspose 精确。
使用 Apache POI + iText (开源,但实现复杂)
这种方法是“手动”转换,Apache POI 用于读取 Word 文档的内容和样式,然后使用 iText 库根据这些信息重新生成一个 PDF,这种方法最灵活,但也最繁琐。
添加 Maven 依赖
<dependencies>
<!-- Apache POI for reading .docx -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version> <!-- 请使用最新版本 -->
</dependency>
<!-- iText for generating PDF -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- iText for HTML parsing (optional, but can help) -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
编写转换代码 (简化示例)
这是一个概念性的示例,真实的实现需要处理段落、表格、图片、列表、字体、颜色、对齐方式等无数细节,工作量巨大。
import org.apache.poi.xwpf.usermodel.*;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class PoiITextWordToPdfConverter {
public static void main(String[] args) {
String inputPath = "input.docx";
String outputPath = "output_poi_itext.pdf";
try (FileInputStream fis = new FileInputStream(inputPath);
XWPFDocument document = new XWPFDocument(fis);
FileOutputStream fos = new FileOutputStream(outputPath)) {
// 1. 创建 iText Document
Document pdfDoc = new Document(PageSize.A4);
PdfWriter.getInstance(pdfDoc, fos);
pdfDoc.open();
// 2. 遍历 Word 文档中的段落
for (XWPFParagraph paragraph : document.getParagraphs()) {
// 创建 iText 段落
com.itextpdf.text.pdf.PdfPChunk chunk = new com.itextpdf.text.pdf.PdfPChunk(paragraph.getText());
// ... 这里需要手动设置字体、大小、颜色、对齐方式等
// pdfDoc.add(new Paragraph(chunk));
}
// 3. 遍历 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);
}
// 4. 关闭文档
pdfDoc.close();
System.out.println("Word 文档已成功转换为 PDF,文件路径: " + new File(outputPath).getAbsolutePath());
} catch (Exception e) {
System.err.println("转换过程中发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}
优点
- 完全控制:你可以精确控制 PDF 的每一个像素。
- 无外部依赖:除了 POI 和 iText,没有其他黑盒操作。
缺点
- 开发成本极高:需要将 Word 的所有复杂格式(样式、主题、页眉页脚、页码、脚注等)手动映射到 iText 的对象上,工作量巨大。
- 容易出错:很难做到 100% 的格式还原,总有细节被遗漏。
总结与建议
| 场景 | 推荐方案 |
|---|---|
| 企业级应用、对质量要求高、有预算 | Aspose.Words |
| 个人项目、学习、或预算有限的开源项目 | docx4j (需要耐心处理字体和兼容性问题) |
| 需要深度定制 PDF 输出,且不介意自己实现所有细节 | Apache POI + iText (不推荐,除非有特殊需求) |
对于绝大多数 Java 直接使用 Aspose.Words 是最省心、效果最好的选择,你可以先去它的官网下载试用版,体验一下转换效果,如果满意再考虑购买。
