PPT转图片/PDF-实用干货

PPT转图片或者是PDF。也许是日常开发中一个并不常见的需求,网上的技术也五花八门,搜寻一番下自己做了个总结,作者最终使用的是openoffice的方案,当然poi的方案也很优秀

方案1:Spire.Presentation

优点: 速度快、精准,代码简洁、转换的图片无乱码
缺点:不开源,超级贵、免费状态下只能转10页 (我是在web状态下发请求转换的,发现一个请求可以转10页,不知道如果多个线程或者是多次求情控制每次转10页这种方案是否可行)

官网: https://www.e-iceblue.cn (价格很高 )
在这里插入图片描述1. 首先引入maven依赖(这里是免费版)

	<dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.presentation.free</artifactId>
        <version>2.6.1</version>
    </dependency>
    // ppt -> pdf 
    public static void main(String[] args) throws Exception {
        //create a Presentataion instance
        Presentation presentation = new Presentation();
        //load the sample PowerPoint file
        presentation.loadFromFile("C:/Users/Administrator/Desktop/template.pptx");
        //save to PDF file
        presentation.saveToFile("ToPDF.pdf", FileFormat.PDF);
        presentation.dispose();
    }
	
	// ppt -> 图片
	public static void main(String[] args) throws Exception {
        //create a Presentation object 
        Presentation presentation = new Presentation();
        //load an example PPTX file 
        presentation.loadFromFile("C:/Users/Administrator/Desktop/template.pptx");
        //loop through the slides 
        for (int i = 0; i < presentation.getSlides().getCount(); i++) {
            //save each slide as a BufferedImage 
            BufferedImage image = presentation.getSlides().get(i).saveAsImage();
            //save BufferedImage as PNG file format 
            String fileName =  String.format("ToImage-%1$s.png", i);
            ImageIO.write(image, "PNG",new File(fileName));
        }
        presentation.dispose();

    }

方案2:使用POI的ppt工具

优点:开源免费
缺点:转换后图片模糊、部分ppt样式无法转换、部分会出现ppt大小与图片大小不符的问题,另外还存在ppt文字乱码问题、使用该工具pptx的转换效果优于ppt

1.引入maven依赖

	<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>

2.编写代码,2003版本的ppt(后缀是.ppt)、和2007版本的pptx(后缀是.pptx)转换方法不同

/**
 * poi 完成ppt->图片 (可以做进度、图片是一张一张的转换的)
 *
 * @author: Ming
 * @date: 2020/12/7
 */
@Slf4j
public class PoiPPT2Pic {

    /**
     * ppt/pptx转图片
     *
     * @param pptFile    ppt文件
     * @param saveFolder 要转换的图片保存的文件夹
     * @return List集合图片在服务器的绝对路径位置
     * @throws Exception 转换异常
     */
    public static List<String> pptConver2Png(File pptFile, File saveFolder) throws Exception {
        // 获取后缀并校验
        String suffix = pptFile.getName().substring(pptFile.getName().lastIndexOf(".") + 1);
        if (!"ppt".equals(suffix) && !"pptx".equals(suffix)) {
            log.error("文件格式异常,非ppt,pptx");
            throw new RuntimeException("文件格式异常,非ppt,pptx");
        }
        // 调用指定方法
        return "ppt".equals(suffix) ? PPT2Pic.ppt2Png(pptFile, saveFolder) : PPT2Pic.pptx2Png(pptFile, saveFolder);
    }


    /**
     * ppt 转图片
     *
     * @param pptFile    ppt文件
     * @param saveFolder 要转换的图片保存的文件夹
     * @return List集合图片在服务器的绝对路径位置
     * @throws Exception 转换异常
     */
    public static List<String> ppt2Png(File pptFile, File saveFolder) throws Exception {
        log.info("=>ppt路径为:" + pptFile.getAbsolutePath());
        log.info("=>要存储的路径为:" + saveFolder.getAbsolutePath());
        if (!pptFile.exists()) {
            log.error("ppt文件不存在");
            return Collections.emptyList();
        }
        // 路径不存在则创建
        if (!saveFolder.exists()) {
            saveFolder.mkdirs();
        }
        // 指定图片保存的路径
        List<String> pngFileList = new ArrayList<String>();
        // 开始时间
        long startTime = System.currentTimeMillis();
        FileInputStream is = null;
        // 将ppt文件转换成每一帧的图片
        HSLFSlideShow ppt = null;
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            is = new FileInputStream(pptFile);
            ppt = new HSLFSlideShow(is);
            // 指定index
            int idx = 1;
            Dimension pageSize = ppt.getPageSize();
            // 缩放比例 3倍以下会迷糊
            double image_rate = 4.0;
            // 获取高度宽度
            int imageWidth = (int) Math.floor(image_rate * pageSize.getWidth());
            int imageHeight = (int) Math.floor(image_rate * pageSize.getHeight());
            // 循环获取图片
            log.info("=>ppt解析完毕共:" + ppt.getSlides().size() + '张');
            for (HSLFSlide slide : ppt.getSlides()) {
                // 构造输出流和画布
                BufferedImage img = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
                Graphics2D graphics = img.createGraphics();
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                // 设置底色
                graphics.setPaint(Color.white);
                // 绘制区域与缩放比例
                graphics.fill(new Rectangle2D.Float(0, 0, imageWidth, imageHeight));
                graphics.scale(image_rate, image_rate);
                //防止中文乱码 (这里可以为黑体或者宋体)---  即使制定了字体也会出现部分字体或艺术字乱码的现象
                for (HSLFShape shape : slide.getShapes()) {
                    if (shape instanceof HSLFTextShape) {
                        HSLFTextShape hslfTextShape = (HSLFTextShape) shape;
                        for (HSLFTextParagraph hslfTextParagraph : hslfTextShape) {
                            for (HSLFTextRun hslfTextRun : hslfTextParagraph) {
                                hslfTextRun.setFontFamily("黑体");
                            }
                        }
                    }
                }
                // 指定输出流
                FileOutputStream out = null;
                try {
                    // 绘制
                    slide.draw(graphics);
                    File pngFile = new File(saveFolder.getAbsolutePath() + String.format("/%d.png", idx++));
                    out = new FileOutputStream(pngFile);
                    // 输出图片
                    ImageIO.write(img, "png", out);
                    log.info("=>第" + (idx - 1) + "张,存储路径:" + pngFile.getAbsolutePath());
                    pngFileList.add(pngFile.getAbsolutePath());
                } finally {
                    try {
                        if (out != null) {
                            out.flush();
                            out.close();
                        }
                        if (graphics != null) {
                            graphics.dispose();
                        }
                        if (img != null) {
                            img.flush();
                        }
                    } catch (IOException e) {
                        log.error("=>ppt转换流关闭异常", e);
                    }
                }
            }
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (ppt != null) {
                    ppt.close();
                }
            } catch (Exception e) {
                log.error("=>ppt转换流关闭异常", e);
            }
        }
        log.info("=>ppt转换完成,共用时" + ((System.currentTimeMillis() - startTime) / 1000) + "秒");
        return pngFileList;
    }


    /**
     * pptx 转换到png
     *
     * @param pptxFile   ppt文件
     * @param saveFolder 图片保存的文件按夹
     * @return List集合图片在服务器的绝对路径位置
     * @throws Exception 转换异常
     */
    public static List<String> pptx2Png(File pptxFile, File saveFolder) throws Exception {
        log.info("=>ppt路径为:" + pptxFile.getAbsolutePath());
        log.info("=>要存储的路径为:" + saveFolder.getAbsolutePath());
        if (!pptxFile.exists()) {
            log.error("pptx文件不存在");
            return Collections.emptyList();
        }
        // 路径不存在则创建
        if (!saveFolder.exists()) {
            saveFolder.mkdirs();
        }
        List<String> pngFileList = new ArrayList<>();
        long startTime = System.currentTimeMillis();
        FileInputStream is = null;
        // 将ppt文件转换成每一帧的图片
        XMLSlideShow pptx = null;
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            is = new FileInputStream(pptxFile);
            pptx = new XMLSlideShow(is);
            // 指定index
            int idx = 1;
            Dimension pageSize = pptx.getPageSize();
            // 缩放比例 3倍以下会迷糊
            double image_rate = 4.0;
            // 获取高度宽度
            int imageWidth = (int) Math.floor(image_rate * pageSize.getWidth());
            int imageHeight = (int) Math.floor(image_rate * pageSize.getHeight());
            log.info("=>pptx解析完毕共:" + pptx.getSlides().size() + '张');
            for (XSLFSlide xslfSlide : pptx.getSlides()) {
                // 构造输出流和画布
                BufferedImage img = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
                Graphics2D graphics = img.createGraphics();
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                // 设置底色
                graphics.setPaint(Color.white);
                // 绘制区域与缩放比例
                graphics.fill(new Rectangle2D.Float(0, 0, imageWidth, imageHeight));
                graphics.scale(image_rate, image_rate);
                //防止中文乱码 (这里可以为黑体或者宋体)---  即使制定了字体也会出现部分字体或艺术字乱码的现象
                for (XSLFShape shape : xslfSlide.getShapes()) {
                    if (shape instanceof XSLFTextShape) {
                        XSLFTextShape xslfTextShape = (XSLFTextShape) shape;
                        for (XSLFTextParagraph xslfTextParagraph : xslfTextShape) {
                            for (XSLFTextRun xslfTextRun : xslfTextParagraph) {
                                xslfTextRun.setFontFamily("黑体");
                            }
                        }
                    }
                }
                // 指定输出流
                FileOutputStream out = null;
                try {
                    xslfSlide.draw(graphics);
                    File pngFile = new File(saveFolder.getAbsolutePath() + String.format("/%d.png", idx++));
                    out = new FileOutputStream(pngFile);
                    // 输出图片
                    ImageIO.write(img, "png", out);
                    pngFileList.add(pngFile.getAbsolutePath());
                    log.info("=>第" + (idx - 1) + "张,存储路径:" + pngFile.getAbsolutePath());
                } finally {
                    try {
                        if (out != null) {
                            out.flush();
                            out.close();
                        }
                        if (graphics != null) {
                            graphics.dispose();
                        }
                        if (img != null) {
                            img.flush();
                        }
                    } catch (IOException e) {
                        log.error("=>pptx转换流关闭异常", e);
                    }
                }
            }
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (pptx != null) {
                    pptx.close();
                }
            } catch (Exception e) {
                log.error("=>pptx转换流关闭异常", e);
            }
        }
        log.info("=>pptx转换完成,共用时" + ((System.currentTimeMillis() - startTime) / 1000) + "秒");
        return pngFileList;
    }

    public static void main(String[] args) throws Exception {
        PPT2Pic.pptConver2Png(new File("C:\\Users\\Ming\\Desktop\\烟台家宽建维协同管理系统介绍材料.pptx"),
                new File("C:\\Users\\Ming\\Desktop\\新建文件夹\\123"));
    }
}

方案3:使用openoffice

优点: 免费、转换准确度搞
缺点:需要第三方软件支持、占用一定内存、转换时间较长,另外openoffice只能实现ppt转pdf,pdf转图片需要另外编写代码

OpenOffice.org 是一套跨平台的办公室软件套件,能在 Windows、Linux、MacOS X (X11)、和 Solaris 等操作系统上执行。它与各个主要的办公室软件套件兼容。OpenOffice.org 是自由软件,任何人都可以免费下载、使用、及推广它。
官方下载地址:http://www.openoffice.org/ (需要安装)
在这里插入图片描述1. 引入jar包
注意: 这里有两种方案完成转换
1.是在程序运行前通过命令的方式启动openoffice
2.是在程序运行中通过代码启动,转换完毕后后关闭
二者基于的jar包不同 ,请仔细阅读maven依赖中后两个依赖的说明

		<dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>jurt</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>ridl</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>juh</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openoffice</groupId>
            <artifactId>unoil</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- 注意:jodconverter的2.2.2版本在中央仓库不具备,需要大家下载后手动安装到本地仓库
            下载地址如下https://sourceforge.net/projects/jodconverter/files/JODConverter/
 			此外:2.2.1是不兼容docx和pptx的若需要兼容则采用2.2.2或者修改默认类配置
			具体修改可参考:https://blog.csdn.net/zhangjunli/article/details/104941509
            若采用jodconverter-core的方式则无关这个jar,也不需要关注兼容性问题
		-->
        <dependency>
            <groupId>com.artofsolving</groupId>
            <artifactId>jodconverter</artifactId>
            <version>2.2.1</version>
        </dependency>
        <!--  这个jar包是实现openOffice服务程序代码中启动的jar,与上边的jar包属于两种工作方式 --->
        <dependency>
            <groupId>com.github.livesense</groupId>
            <artifactId>jodconverter-core</artifactId>
            <version>1.0.5</version>
        </dependency>

2.编写代码

1>方式1:命令式启动 + 代码转换
进入openoffice安装目录,通过cmd启动一个soffice服务,
启动的命令是
	soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;"
/**
     * 将ppt转换为pdf, 这个方法其实可用于docx ppt等转换为pdf 或者html
     * @param sourceFile ppt文件
     * @param pdfFile 要输出的pdf文件路径+名字
     * @return  pdf绝对路径
     * @throws Exception 转换异常
     */
    public static String officeToPDF(File sourceFile, File pdfFile) throws Exception {
        // 获取后缀并校验
        String suffix = sourceFile.getName().substring(sourceFile.getName().lastIndexOf(".") + 1);
        if (!"ppt".equals(suffix) && !"pptx".equals(suffix)) {
            log.error("文件格式异常,非ppt,pptx");
            throw new RuntimeException("文件格式异常,非ppt,pptx");
        }
        if (!sourceFile.exists()) {
            // 找不到源文件, 则返回false
            throw new RuntimeException("ppt文件不存在");
        }
        // 如果目标路径不存在, 则新建该路径
        if (!pdfFile.getParentFile().exists()) {
            pdfFile.getParentFile().mkdirs();
        }
        // 获取openOffice服务的链接。默认为8100
        OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1", 8100);
        connection.connect();
        //用于测试openOffice连接时间
        log.info("链接成功,开始转换");
        long start = System.currentTimeMillis();
        DocumentConverter converter = new StreamOpenOfficeDocumentConverter(
                connection);
        converter.convert(sourceFile, pdfFile);
        //测试word转PDF的转换时间
        log.info("转换结束:" + ((System.currentTimeMillis() - start) / 1000));
        connection.disconnect();
        return pdfFile.getAbsolutePath();
    }
// ========================================================    
2> 方式2:程序中启动关闭openOffice服务
/**
     *  打开服务器
     * @return
     */
    public static OfficeManager startService() {
        OfficeManager officeManage = null;
        DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
        try {
            log.info("=>openOffice准备启动服务....");
            configuration.setOfficeHome("C:\\Program Files (x86)\\OpenOffice 4");// 设置OpenOffice.org安装目录
            configuration.setPortNumbers(8100); // 设置转换端口,默认为8100
            configuration.setTaskExecutionTimeout(1000 * 60 * 5L);// 设置任务执行超时为5分钟
            configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为24小时
            officeManage = configuration.buildOfficeManager();
            officeManage.start(); // 启动服务
            log.info("=>openOffice服务启动成功");
        } catch (Exception ce) {
            log.info("openOffice转换服务启动失败!详细信息:" + ce);
        }
        return officeManage;
    }


    // 关闭服务器
    public static void stopService(OfficeManager officeManager) {
        log.info("=>关闭office转换服务....");
        if (officeManager != null) {
            officeManager.stop();
        }
        log.info("=>关闭office转换成功!");
    }

    /**
     *  ppt 转pdf java程序启动方式
     * @param sourceFile
     * @param pdfFile
     * @throws FileNotFoundException
     */
    public static String convert2PDF(File sourceFile, File pdfFile) throws FileNotFoundException {
        // 获取后缀并校验
        String suffix = sourceFile.getName().substring(sourceFile.getName().lastIndexOf(".") + 1);
        if (!"ppt".equals(suffix) && !"pptx".equals(suffix)) {
            log.error("文件格式异常,非ppt,pptx");
            throw new RuntimeException("文件格式异常,非ppt,pptx");
        }
        if (!sourceFile.exists()) {
            // 找不到源文件, 则返回false
            throw new RuntimeException("ppt文件不存在");
        }
        OfficeManager officeManager = startService();
        if (officeManager ==null) {
            throw  new RuntimeException("openOffice服务启动失败");
        }
        log.info("=>进行文档转换转换:" + sourceFile.getAbsolutePath() + " --> " + pdfFile.getAbsolutePath());
        long start = System.currentTimeMillis();
        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
        // 如果目标路径不存在, 则新建该路径
        if (!pdfFile.getParentFile().exists()) {
            pdfFile.getParentFile().mkdirs();
        }
        converter.convert(sourceFile,pdfFile);
        log.info("转换成功:" + ((System.currentTimeMillis() - start) / 1000));
        stopService(officeManager);
        return  pdfFile.getAbsolutePath();
    }

测试发现jodconverter-core的方式通过wps打开的ppt无法完成转换,pptx可以转换,office打开的ppt和pptx都可以

这里顺便说一下pdf转图片,使用pdfbox

  1. 引入依赖
		<dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.20</version>
        </dependency>
  1. 实现代码转换
/**
     * dpi越大转换后越清晰,相对转换速度越慢
     */
    private static final Integer DPI = 100;

    /**
     * 转换后的图片类型
     */
    private static final String IMG_TYPE = "png";
   
	/**
     * pdf转图片
     *
     * @param pdfFile pdf路径
     * @param folderPath 图片保存位置
     * @return
     * @throws IOException
     */
	public static List<String> pdfToImage(File pdfFile, File folderPath) throws IOException {
        log.info("=>pdf转图片");
        log.info("=>pdf路径为:" + pdfFile.getAbsolutePath());
        log.info("=>要存储的图片路径为:" + folderPath.getAbsolutePath());
        long start =  System.currentTimeMillis();
        // 返回值
        List<String> result = new ArrayList<>();
        log.info("=>正在读取pdf");
        PDDocument document = PDDocument.load(new FileInputStream(pdfFile));
        PDFRenderer renderer = new PDFRenderer(document);
        FileOutputStream out = null;
        log.info("=>读取完毕开始转换,共"+document.getNumberOfPages() +"张");
        for (int i = 0; i < document.getNumberOfPages(); ++i) {
            BufferedImage bufferedImage = renderer.renderImageWithDPI(i, DPI);
            File pngFile = new File(folderPath.getAbsolutePath() + String.format("/%d.png", (i+1)));
            out = new FileOutputStream(pngFile);
            ImageIO.write(bufferedImage, IMG_TYPE, out);
            log.info("=>第"+(i+1)+"张转换完毕,"+pngFile.getAbsolutePath());
            result.add(pngFile.getAbsolutePath());
            out.close();
        }
        log.info("=>转换结束-成功," + ((System.currentTimeMillis() - start) / 1000) + "秒");
        return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值