杰瑞科技汇

Java PPT如何转PDF?

使用 Apache POI + Apache PDFBox (纯 Java 开源方案)

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

Java PPT如何转PDF?-图1
(图片来源网络,侵删)
  • 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 PPT如何转PDF?-图2
(图片来源网络,侵删)

核心思想: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)

商业组件是平衡了功能、保真度和开发成本的“付费”方案,在企业和专业开发中非常流行。

Java PPT如何转PDF?-图3
(图片来源网络,侵删)
  • 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),它用最少的代码提供了最稳定、最可靠的功能,是绝大多数专业开发者的首选。
分享:
扫描分享到社交APP
上一篇
下一篇