JAVA实现把PPT转PDF的方法

本文介绍了一种使用Apache POI将PPT或PPTX文件转换为PDF的方法。该工具支持将转换后的PDF以InputStream形式返回,便于上传至云端存储,并提供了基于文件路径直接生成PDF的功能。


前言

项目里前端想要上传的ppt转成pdf之后上传oss,好方便前端在页面中预览。找了好几个ppt转pdf的方案, 最终选择Apache poi

  1. 使用jacob可以将office文件转换成pdf,因为需要依赖Microsoft Office,适用于windows服务器部署的项目。(项目部署在linux服务器上, 所以排除了这个方案)
  2. 如果需要用Linux服务器,请考虑使用OpenOffice方案 (因为这个方案需要在服务器上安装OpenOffice, 所以也排除了)
  3. Apache poi 也就是本次的主角

一、Apache poi是什么?

  • Apache POI 简介是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“可怜的模糊实现”。

二、具体实现

1. 引入依赖

		<!--  poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>

        <!-- itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.3</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

2. ppt/pptx转换pdf (返回InputStream)

由于ppt和pptx文件格式不同,ppt是基于二进制的文件,而pptx是基于xml文件, 也是就pptx是2007年后出现的新的ppt版本,对这两种文件处理方式转换PDF其实都差不多,只是要注意接收文件ppt或pptx以及获取两种文件内容 需要的类处理,即使用POI 里面的XMLSlide 和 HSLFSlide 进行分别处理。

因为最后是要把文件上传到阿里云oss, 需要的是InputStream, 所以这里返回的是转化后pdf的InputStream

/**
 * @author ErrorRua
 * @date 2022/11/17
 * @description: 转换PPT为PDF工具类
 */
public final class PdfConvertUtil {


    /**
     * @description: pptxToPdf
     * @param pptIs:
     * @return java.io.InputStream
     * @author ErrorRua
     * @date 2022/11/21
     */
    public static InputStream pptToPdf(InputStream pptIs) {


        Document document = null;
        PdfWriter pdfWriter = null;


        try (HSLFSlideShow hslfSlideShow = new HSLFSlideShow(pptIs);
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()
            ) {

            // 获取ppt文件页面
            Dimension dimension = hslfSlideShow.getPageSize();

            document = new Document();

//             pdfWriter实例
            pdfWriter = PdfWriter.getInstance(document, byteArrayOutputStream);

            document.open();

            PdfPTable pdfPTable = new PdfPTable(1);

            List<HSLFSlide> hslfSlideList = hslfSlideShow.getSlides();

            for (HSLFSlide hslfSlide : hslfSlideList) {
                // 设置字体, 解决中文乱码
                for (HSLFShape shape : hslfSlide.getShapes()) {
                    HSLFTextShape textShape = (HSLFTextShape) shape;

                    for (HSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
                        for (HSLFTextRun textRun : textParagraph.getTextRuns()) {
                            textRun.setFontFamily("宋体");
                        }
                    }
                }
                BufferedImage bufferedImage = new BufferedImage((int) dimension.getWidth(), (int) dimension.getHeight(), BufferedImage.TYPE_INT_RGB);

                Graphics2D graphics2d = bufferedImage.createGraphics();

                graphics2d.setPaint(Color.white);
                graphics2d.setFont(new Font("宋体", Font.PLAIN, 12));

                hslfSlide.draw(graphics2d);

                graphics2d.dispose();

                Image image = Image.getInstance(bufferedImage, null);
                image.scalePercent(50f);

                // 写入单元格
                pdfPTable.addCell(new PdfPCell(image, true));
                document.add(image);
            }

            return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (document != null) {
                document.close();
            }
            if (pdfWriter != null) {
                pdfWriter.close();
            }
        }
    }

    /**
     * @description: pptxToPdf
     * @param pptIs:
     * @return java.io.InputStream
     * @author ErrorRua
     * @date 2022/11/21
     */
    public static InputStream pptxToPdf(InputStream pptIs) {


        Document document = null;

        PdfWriter pdfWriter = null;


        try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
              XMLSlideShow slideShow = new XMLSlideShow(pptIs);) {


            Dimension dimension = slideShow.getPageSize();

            document = new Document();

            pdfWriter = PdfWriter.getInstance(document, byteArrayOutputStream);

            document.open();

            PdfPTable pdfPTable = new PdfPTable(1);

            List<XSLFSlide> slideList = slideShow.getSlides();


            for (XSLFSlide slide : slideList) {

                // 设置字体, 解决中文乱码
                for (XSLFShape shape : slide.getShapes()) {
                    XSLFTextShape textShape = (XSLFTextShape) shape;

                    for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
                        for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
                            textRun.setFontFamily("宋体");
                        }
                    }
                }

                BufferedImage bufferedImage = new BufferedImage((int) dimension.getWidth(), (int) dimension.getHeight(), BufferedImage.TYPE_INT_RGB);

                Graphics2D graphics2d = bufferedImage.createGraphics();

                graphics2d.setPaint(Color.white);
                graphics2d.setFont(new Font("宋体", Font.PLAIN, 12));

                slide.draw(graphics2d);

                graphics2d.dispose();

                Image image = Image.getInstance(bufferedImage, null);
                image.scalePercent(50f);

                // 写入单元格
                pdfPTable.addCell(new PdfPCell(image, true));
                document.add(image);
            }

            return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());


        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (document != null) {
                document.close();
            }
            if (pdfWriter != null) {
                pdfWriter.close();
            }
        }
    }

}

3. ppt/pptx转换pdf (返回pdf文件)

import cn.hutool.core.util.StrUtil;

import java.awt.*;
import java.awt.image.BufferedImage;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.hslf.usermodel.*;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.Image;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * 类名称:PdfConvertUtil
 * 类描述:转为为PDF工具类
*/
public final class PdfConverUtil {

/**
	 * pptToPdf
	 * @param pptPath PPT文件路径
	 * @param pdfDir 生成的PDF文件路径
	 * @return
	 */
	public static boolean pptToPdf(String pptPath, String pdfDir) {

        if (StrUtil.isEmpty(pptPath)) {
            throw new RuntimeException("word文档路径不能为空");
        }

        if (StrUtil.isEmpty(pdfDir)) {
            throw new RuntimeException("pdf目录不能为空");
        }
        
        
        String pdfPath = pdfDir + StrUtil.sub(pptPath, pptPath.lastIndexOf(StrUtil.BACKSLASH), pptPath.lastIndexOf(StrUtil.DOT)) + StrUtil.DOT + "pdf";

        Document document = null;
        HSLFSlideShow hslfSlideShow = null;
        FileOutputStream fileOutputStream = null;
        PdfWriter pdfWriter = null;

        try {
            hslfSlideShow = new HSLFSlideShow(new FileInputStream(pptPath));

            // 获取ppt文件页面
            Dimension dimension = hslfSlideShow.getPageSize();

            fileOutputStream = new FileOutputStream(pdfPath);

            document = new Document();
            
            // pdfWriter实例
            pdfWriter = PdfWriter.getInstance(document, fileOutputStream);

            document.open();

            PdfPTable pdfPTable = new PdfPTable(1);
           
            List<HSLFSlide> hslfSlideList = hslfSlideShow.getSlides();

            for (int i=0; i < hslfSlideList.size(); i++) {
                HSLFSlide hslfSlide = hslfSlideList.get(i);
                // 设置字体, 解决中文乱码
                for (HSLFShape shape : hslfSlide.getShapes()) {
                    HSLFTextShape textShape = (HSLFTextShape) shape;

                    for (HSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
                        for (HSLFTextRun textRun : textParagraph.getTextRuns()) {
                            textRun.setFontFamily("宋体");
                        }
                    }
                }
                BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB);

                Graphics2D graphics2d = bufferedImage.createGraphics();

                graphics2d.setPaint(Color.white);
                graphics2d.setFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 12));

                hslfSlide.draw(graphics2d);

                graphics2d.dispose();

                Image image = Image.getInstance(bufferedImage, null);
                image.scalePercent(50f);

                // 写入单元格
                pdfPTable.addCell(new PdfPCell(image, true));
                document.add(image);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (document != null) {
                    document.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                if (pdfWriter != null) {
                    pdfWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

	/**
	 *
	 * @Title: pptxToPdf
	 * @param pptPath PPT文件路径
	 * @param pdfDir 生成的PDF文件路径
	 */
	public static boolean pptxToPdf(String pptPath, String pdfDir) {

		if (StrUtil.isEmpty(pptPath)) {
			throw new RuntimeException("word文档路径不能为空");
		}

		if (StrUtil.isEmpty(pdfDir)) {
			throw new RuntimeException("pdf目录不能为空");
		}

		String pdfPath = pdfDir + StrUtil.sub(pptPath, pptPath.lastIndexOf(StrUtil.BACKSLASH), pptPath.lastIndexOf(StrUtil.DOT)) + StrUtil.DOT + "pdf";

		Document document = null;

		XMLSlideShow slideShow = null;


		FileOutputStream fileOutputStream = null;

		PdfWriter pdfWriter = null;


		try {

			slideShow = new XMLSlideShow(new FileInputStream(pptPath));

			Dimension dimension = slideShow.getPageSize();

			fileOutputStream = new FileOutputStream(pdfPath);

			document = new Document();

			pdfWriter = PdfWriter.getInstance(document, fileOutputStream);

			document.open();

			PdfPTable pdfPTable = new PdfPTable(1);

			List<XSLFSlide> slideList = slideShow.getSlides();

			for (int i = 0, row = slideList.size(); i < row; i++) {

				XSLFSlide slide = slideList.get(i);

				// 设置字体, 解决中文乱码
				for (XSLFShape shape : slide.getShapes()) {
					XSLFTextShape textShape = (XSLFTextShape) shape;

					for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
						for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
							textRun.setFontFamily("宋体");
						}
					}
				}

				BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB);

				Graphics2D graphics2d = bufferedImage.createGraphics();

				graphics2d.setPaint(Color.white);
				graphics2d.setFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 12));

				slide.draw(graphics2d);

				graphics2d.dispose();

				Image image = Image.getInstance(bufferedImage, null);
				image.scalePercent(50f);

				// 写入单元格
				pdfPTable.addCell(new PdfPCell(image, true));
				document.add(image);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				if (document != null) {
					document.close();
				}
				if (fileOutputStream != null) {
					fileOutputStream.close();
				}
				if (pdfWriter != null) {
					pdfWriter.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

}


相关文章:

<think> 首先,用户的问题是:“我想查找使用Java语言实现PPT文件换为PDF文件的方法 请问Java实现PPTPDF方法”。所以,我需要基于之前的引用提供Java实现PPTPDF方法。 回顾系统级指令: - 所有行内数学表达式必须用$...$格式(但这里可能不涉及数学)。 - 独立公式用$$...$$并单独成段(可能不适用)。 - LaTeX语法正确(但内容主要是代码和文本)。 - 使用中文回答。 - 生成相关问题(在回答末尾)。 - 引用中引用的段落末尾自然地添加引用标识。 用户提供的引用: - [^1]: 提到Aspose库实现Java PPTPDF。 - [^2]: 使用poi将PPT图片,然后用itextpdfPDF。 - [^3]: 使用Aspose.Slides库。 - [^4]: 区分PPTPPTX格式,使用POI处理。 - [^5]: 使用Jacob库。 用户上次的问题是询问Java实现PPTPDF方法,所以我的回答需要结构化,清晰解答。 回答结构: 1. **介绍方法**:总结不同的Java实现PPTPDF方法。 2. **详细步骤**:基于引用,提供主要方法的代码示例或描述。 3. **优缺点**:简要比较不同方法(可选)。 4. **生成相关问题**:在末尾添加相关问题。 关键方法: - **使用Aspose库**:引用[1]和[3]提到Aspose.Slides,这是一个商业库,提供直接换。 - **使用POI和iText**:引用[2]和[4]提到Apache POI处理PPT/PPTX,成图片,然后用iTextPDFPDF。 - **使用Jacob**:引用[5]提到Jacob,一个Java COM桥接库,可能依赖Microsoft Office。 因为Aspose是商业库,POI和iText是开源的,Jacob可能需要Office安装。 回答中使用中文。 添加引用标识:在描述方法时,末尾自然地添加,例如[^1]。 生成相关问题:在末尾添加§§相关问题§§部分。 结构化回答: - **引言**:简要介绍Java实现PPTPDF的常见方法。 - **方法一:使用Aspose.Slides库**:描述步骤和代码片段。 - **方法二:使用Apache POI和iTextPDF**:描述步骤和代码片段。 - **方法三:使用Jacob库**:简要描述(因为它可能需要特定环境)。 - **比较和建议**:简短比较不同方法的优缺点。 - **相关问题**:添加几个相关问题。 确保代码格式正确:使用Markdown代码块。 代码示例: - 基于引用[1]和[3]的Aspose示例。 - 基于引用[2]和[4]的POI和iText示例。 - 基于引用[5]的Jacob示例(如果需要)。 引用添加: - 当提到Aspose方法时,添加[^1]或[^3]。 - 当提到POI方法时,添加[^2]或[^4]。 - 当提到Jacob时,添加[^5]。 最终生成相关问题: 例如: 1. Aspose.Slides库的优缺点是什么? 2. POI处理PPTPPTX的区别? 3. 如何优化PPTPDF的性能? 现在,起草回答。 </think> ### Java实现PPTPDF方法Java实现PPT文件换为PDF文件,有多种常用方法。我将基于您的引用信息,详细解释三种主流方案:使用Aspose.Slides库、Apache POI结合iTextPDF库,以及Jacob库。每种方法都提供核心代码示例和步骤说明。注意,PPTPPTX格式有所区别(PPTX基于XML,而PPT基于二进制),换时需分别处理[^4]。 #### 方法一:使用Aspose.Slides库(商业库,推荐直接换) Aspose.Slides是一个专业的Java库,支持PPT/PPTX到PDF的直接换,无需中间步骤。优点是简单高效,但需要商业许可证。 **步骤:** 1. **添加依赖**:在Maven项目中添加Aspose.Slides依赖。 2. **加载PPT文件**:使用`Presentation`类加载PPTPPTX文件。 3. **换并保存**:调用`save`方法输出PDF文件。 **代码示例:** ```java import com.aspose.slides.Presentation; import com.aspose.slides.SaveFormat; public class AsposePptToPdf { public static void convert(String inputPath, String outputPath) { // 加载PPT文件 Presentation pres = new Presentation(inputPath); try { // 保存为PDF pres.save(outputPath, SaveFormat.Pdf); System.out.println("换成功!"); } catch (Exception e) { e.printStackTrace(); } finally { if (pres != null) pres.dispose(); } } public static void main(String[] args) { convert("input.ppt", "output.pdf"); // 支持.ppt和.pptx } } ``` **说明**:Aspose.Slides库处理所有格式换细节,性能稳定,适合企业级应用[^1][^3]。 #### 方法二:使用Apache POI和iTextPDF(开源方案,需中间换) 此方法先将PPT成图片,再将图片合成PDF。优点是开源免费,但多步操作可能影响性能。 **步骤:** 1. **添加依赖**:在Maven中添加POI和iTextPDF依赖。 2. **PPT图片**:使用POI读取PPT/PPTX文件,逐页渲染为图片(如PNG)。 3. **图片PDF**:使用iTextPDF创建PDF文档,添加图片并保存。 **代码示例:** ```java import org.apache.poi.hslf.usermodel.HSLFSlideShow; // 用于PPT import org.apache.poi.xslf.usermodel.XMLSlideShow; // 用于PPTX import com.itextpdf.text.Document; import com.itextpdf.text.Image; import com.itextpdf.text.pdf.PdfWriter; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.*; public class PoiToPdf { public static void convert(String inputPath, String outputPath) throws Exception { Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(outputPath)); document.open(); // 根据文件后缀选择SlideShow类 if (inputPath.endsWith(".ppt")) { HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(inputPath)); for (org.apache.poi.hslf.model.Slide slide : ppt.getSlides()) { BufferedImage img = new BufferedImage(slide.getSlideShow().getPageSize().width, slide.getSlideShow().getPageSize().height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); slide.draw(graphics); graphics.dispose(); Image pdfImage = Image.getInstance(img, null); document.add(pdfImage); } ppt.close(); } else if (inputPath.endsWith(".pptx")) { XMLSlideShow pptx = new XMLSlideShow(new FileInputStream(inputPath)); Dimension pgsize = pptx.getPageSize(); for (org.apache.poi.xslf.usermodel.XSLFSlide slide : pptx.getSlides()) { BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); slide.draw(graphics); graphics.dispose(); Image pdfImage = Image.getInstance(img, null); document.add(pdfImage); } pptx.close(); } document.close(); } public static void main(String[] args) { try { convert("input.pptx", "output.pdf"); // 支持.ppt和.pptx } catch (Exception e) { e.printStackTrace(); } } } ``` **说明**:此方法需区分PPTPPTX格式处理,Apache POI生成图片后,iTextPDF合成PDF[^2][^4]。 #### 方法三:使用Jacob库(依赖Microsoft Office) Jacob库通过COM接口调用本地Microsoft Office程序实现换。优点是兼容性强,但需要安装Office且仅用于Windows环境。 **步骤:** 1. **添加依赖**:在Maven中添加Jacob依赖。 2. **调用Office API**:使用Jacob的`ComThread`和`Dispatch`类操作PowerPoint应用程序。 3. **换并保存**:打开PPT文件,另存为PDF。 **代码示例:** ```java import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import com.jacob.com.Variant; public class JacobPptToPdf { public static void convert(String inputPath, String outputPath) { ComThread.InitSTA(); // 初始化COM线程 ActiveXComponent pptApp = null; try { pptApp = new ActiveXComponent("PowerPoint.Application"); Dispatch presentations = pptApp.getProperty("Presentations").toDispatch(); Dispatch presentation = Dispatch.call(presentations, "Open", inputPath, true).toDispatch(); Dispatch.call(presentation, "SaveAs", outputPath, 32); // 32是PDF格式的常量 Dispatch.call(presentation, "Close"); } catch (Exception e) { e.printStackTrace(); } finally { if (pptApp != null) pptApp.invoke("Quit"); ComThread.Release(); // 释放资源 } } public static void main(String[] args) { convert("input.ppt", "output.pdf"); // 支持.ppt和.pptx } } ``` **说明**:Jacob需Windows系统和Office安装,适合本地环境[^5]。 #### 方法比较与建议 - **Aspose.Slides**:最便捷高效,但需付费(免费试用有水印),适合商业项目[^1][^3]。 - **POI + iTextPDF**:开源免费,部署灵活,但性能较低(多步换),适合简单场景[^2][^4]。 - **Jacob**:依赖Office,跨平台差,仅推荐特定环境使用[^5]。 建议根据项目需求:追求效率选Aspose;预算有限选POI+iText;避免依赖Office。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值