使用 Apache POI + Apache PDFBox (纯 Java 开源方案)
这是最推荐的纯 Java 开源方案,它不依赖任何外部软件(如 Microsoft Office),可以在服务器端稳定运行。

- Apache POI: 用于读取和操作
.ppt和.pptx文件。 - Apache PDFBox: 用于将 POI 解析后的内容渲染并生成 PDF 文件。
核心思想:POI 负责解析 PPT 的结构(幻灯片、文本、图片、形状等),然后我们遍历这些元素,使用 PDFBox 的 API 在 PDF 页面上重新绘制它们。
添加 Maven 依赖
在你的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- Apache POI for PPT/PPTX -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- Apache PDFBox for PDF generation -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.27</version>
</dependency>
</dependencies>
完整代码示例
这个代码会遍历 PPT 的每一页,将文本和图片提取出来,并添加到对应的 PDF 页面中。
import org.apache.poi.xslf.usermodel.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class PptToPdfConverter {
public static void main(String[] args) {
// 输入的 PPT/PPTX 文件路径
String pptFilePath = "path/to/your/presentation.pptx";
// 输出的 PDF 文件路径
String pdfFilePath = "path/to/your/output.pdf";
try (FileInputStream fis = new FileInputStream(pptFilePath);
XMLSlideShow ppt = new XMLSlideShow(fis);
PDDocument pdfDoc = new PDDocument()) {
// 1. 遍历 PPT 的每一页幻灯片
for (XSLFSlide slide : ppt.getSlides()) {
// 为 PPT 的每一页创建一个对应的 PDF 页面
// PDF 页面大小设置为 PPT 幻灯片的大小
PDRectangle pageSize = new PDRectangle(
(float) slide.getSlideSize().getWidth(),
(float) slide.getSlideSize().getHeight()
);
PDPage pdfPage = new PDPage(pageSize);
pdfDoc.addPage(pdfPage);
// 2. 获取 PDF 页面的绘图流
try (PDPageContentStream contentStream = new PDPageContentStream(pdfDoc, pdfPage)) {
// 3. 遍历 PPT 幻灯片上的每一个形状
for (XSLFShape shape : slide) {
if (shape instanceof XSLFTextShape) {
// 处理文本形状
drawTextShape(contentStream, (XSLFTextShape) shape);
} else if (shape instanceof XSLFPictureShape) {
// 处理图片形状
drawPictureShape(contentStream, (XSLFPictureShape) shape, pdfDoc);
}
// 可以继续添加对其他形状类型的处理,如表格、图形等
}
}
}
// 4. 保存 PDF 文件
pdfDoc.save(pdfFilePath);
System.out.println("PPT 转 PDF 成功!文件已保存至: " + pdfFilePath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 绘制文本形状到 PDF
*/
private static void drawTextShape(PDPageContentStream contentStream, XSLFTextShape shape) throws IOException {
for (XSLFTextParagraph paragraph : shape) {
for (XSLFTextRun run : paragraph) {
// 设置字体和大小 (这里简化处理,实际应用中需要更复杂的字体映射)
contentStream.setFont(PDType1Font.HELVETICA, (float) run.getFontSize());
// 设置颜色 (简化处理)
contentStream.setNonStrokingColor(run.getFontColor());
// 获取文本内容
String text = run.getText();
// 获取文本位置
Rectangle2D anchor = paragraph.getAnchor();
// 在 PDF 上绘制文本
contentStream.beginText();
contentStream.newLineAtOffset((float) anchor.getX(), (float) anchor.getY());
contentStream.showText(text);
contentStream.endText();
}
}
}
/**
* 绘制图片形状到 PDF
*/
private static void drawPictureShape(PDPageContentStream contentStream, XSLFPictureShape pictureShape, PDDocument pdfDoc) throws IOException {
XSLFPictureData pictureData = pictureShape.getPictureData();
// 将图片数据转换为 PDFBox 能处理的 PDImageXObject
// 注意:这里需要将 byte[] 转换为 PDImageXObject
// 由于 POI 和 PDFBox 的图片处理方式不同,这里需要额外处理
// 这是一个简化的示例,实际可能需要更复杂的图像转换逻辑
// 可以使用 ImageIO 读取 byte[] 得到 BufferedImage,然后再用 PDImageXObject.createFromByteArray
// 伪代码,实际实现需要处理图像格式转换
// PDImageXObject pdImage = PDImageXObject.createFromByteArray(pdfDoc, pictureData.getData(), pictureData.getFileName());
// Rectangle2D anchor = pictureShape.getAnchor();
// contentStream.drawImage(pdImage, (float) anchor.getX(), (float) anchor.getY(), (float) anchor.getWidth(), (float) anchor.getHeight());
System.out.println("提示:图片处理逻辑需要根据具体需求进一步完善,涉及图像格式转换。");
}
}
方案优缺点
- 优点:
- 纯 Java 实现: 无需安装 Office 软件,可在任何支持 Java 的环境(如服务器)中运行。
- 开源免费: 无需支付任何费用。
- 轻量级: 相比调用 Office API,资源占用更少。
- 缺点:
- 实现复杂度高: 需要手动处理 PPT 中的每一种元素(文本、字体、颜色、图片、表格、动画、复杂布局等),工作量巨大。
- 保真度问题: 难以 100% 还原 PPT 的原始样式和布局,特别是对于复杂的图形、艺术字和精确的排版。
- 功能有限: 对于 PPT 中的高级功能(如宏、嵌入的音频/视频)支持几乎为零。
调用 Microsoft Office COM 自动化 (仅限 Windows)
如果你的应用运行在 Windows 平台上,并且已经安装了 Microsoft PowerPoint,那么可以通过调用其 COM 接口来实现转换,这种方法能获得最高的保真度。

核心思想:Java 通过 JNI (Java Native Access) 或其他库调用 Windows 的 COM 接口,像 VBA 脚本一样控制 PowerPoint 应用程序打开文件并执行“另存为 PDF”的操作。
添加依赖 (使用 Jacob)
Jacob (Java-COM Bridge) 是一个常用的库。
<dependency>
<groupId>net.sf.jacob-project</groupId>
<artifactId>jacob</artifactId>
<version>1.20</version>
</dependency>
注意: 你还需要下载 jacob.dll 文件,并将其放在 JAVA_HOME/bin 目录下,或者你的项目输出目录中。
完整代码示例
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class PptToPdfWithOffice {
public static void main(String[] args) {
// 输入的 PPT/PPTX 文件路径
String pptFilePath = "C:\\path\\to\\your\\presentation.pptx";
// 输出的 PDF 文件路径
String pdfFilePath = "C:\\path\\to\\your\\output.pdf";
// 1. 启动 PowerPoint 应用
ActiveXComponent ppt = new ActiveXComponent("PowerPoint.Application");
try {
// 设置 PowerPoint 为不可见模式
Dispatch.put(ppt, "Visible", new Variant(false));
Dispatch presentations = Dispatch.get(ppt, "Presentations").toDispatch();
// 2. 打开 PPT 文件
Dispatch presentation = Dispatch.call(presentations, "Open", pptFilePath, true, true, false).toDispatch();
// 3. 另存为 PDF
// 32 是 ppSaveAsPDF 的常量值
Dispatch.call(presentation, "SaveAs", pdfFilePath, 32);
// 4. 关闭演示文稿
Dispatch.call(presentation, "Close");
System.out.println("PPT 转 PDF 成功!文件已保存至: " + pdfFilePath);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5. 退出 PowerPoint 应用
Dispatch.call(ppt, "Quit");
ppt.safeRelease();
}
}
}
方案优缺点
- 优点:
- 保真度极高: 因为是直接调用 PowerPoint 渲染引擎,所以能完美还原所有样式、布局和复杂图形。
- 实现简单: 代码量少,逻辑清晰。
- 缺点:
- 平台限制: 仅限 Windows,无法在 Linux 或 macOS 上运行。
- 依赖 Office: 必须目标机器上安装 Microsoft PowerPoint。
- 性能和资源: 每次转换都需要启动一个完整的 Office 进程,消耗较多内存和 CPU,不适合高并发场景。
- 稳定性问题: Office 进程可能因各种原因崩溃,需要妥善处理异常和资源释放。
使用商业组件 (如 Aspose.Slides)
商业组件是平衡了功能、保真度和开发成本的“付费”方案,在企业和专业开发中非常流行。

- Aspose.Slides: 功能非常强大的 PPT/PPTX 操作库,支持将演示文稿直接导出为 PDF。
核心思想: 使用 Aspose 提供的 API,几行代码就能完成转换,它内部已经处理好了所有复杂的渲染逻辑。
添加 Maven 依赖 (需要申请 License)
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<version>23.8</version> <!-- 请使用最新版本 -->
</dependency>
完整代码示例
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import java.io.File;
public class PptToPdfWithAspose {
public static void main(String[] args) {
// 输入的 PPT/PPTX 文件路径
String pptFilePath = "path/to/your/presentation.pptx";
// 输出的 PDF 文件路径
String pdfFilePath = "path/to/your/output.pdf";
// 如果需要,可以在这里设置 License
// License license = new License();
// license.setLicense("Aspose.Slides.Java.lic");
// 1. 加载 PPT 文件
Presentation pres = new Presentation(pptFilePath);
try {
// 2. 保存为 PDF
// SaveFormat.Pdf 是 Aspose 定义的常量
pres.save(pdfFilePath, SaveFormat.Pdf);
System.out.println("PPT 转 PDF 成功!文件已保存至: " + pdfFilePath);
} finally {
// 3. 释放资源
if (pres != null) {
pres.dispose();
}
}
}
}
方案优缺点
- 优点:
- 功能强大且 API 简洁: 代码量极少,开发效率高。
- 高保真度: 能很好地还原 PPT 的外观和内容。
- 跨平台: 纯 Java 库,可在 Windows, Linux, macOS 上运行。
- 无需安装 Office: 独立运行,不依赖任何外部软件。
- 缺点:
- 需要付费: 商业使用需要购买 License,有免费试用版但有限制。
总结与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Apache POI + PDFBox | 纯 Java,开源免费,轻量 | 实现复杂,保真度低,功能有限 | 简单文本/图片 PPT 的转换,对成本敏感且要求不高的场景。 |
| Office COM 自动化 | 保真度极高,实现简单 | 仅限 Windows,依赖 Office,性能差,不稳定 | Windows 桌面应用,对 PPT 外观要求极其苛刻,且并发量低。 |
| Aspose.Slides | 功能强大,API 简洁,高保真,跨平台 | 需要付费 | 企业级应用,对转换质量、性能和开发效率有较高要求的商业项目。 |
如何选择?
- 如果追求成本最低,且 PPT 内容简单:选择 方法一 (Apache POI + PDFBox),但要有心理准备去处理复杂的渲染逻辑。
- 如果你的应用只在 Windows 上运行,且已经安装了 Office,并且要求 100% 还原:选择 方法二 (Office COM),这是最省心、效果最好的方案。
- 如果是商业项目,预算充足,追求开发效率和高质量转换:强烈推荐 方法三 (Aspose.Slides),它用最少的代码提供了最稳定、最可靠的功能,是绝大多数专业开发者的首选。
