赞
踩
PPT转图片或者是PDF。也许是日常开发中一个并不常见的需求,网上的技术也五花八门,搜寻一番下自己做了个总结,作者最终使用的是openoffice的方案,当然poi的方案也很优秀
优点: 速度快、精准,代码简洁、转换的图片无乱码
缺点:不开源,超级贵、免费状态下只能转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(); }
优点:开源免费
缺点:转换后图片模糊、部分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")); } }
优点: 免费、转换准确度搞
缺点:需要第三方软件支持、占用一定内存、转换时间较长,另外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
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.20</version>
</dependency>
/** * 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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。