前言

背景:最近项目需要实现PPT预览功能,以及项目APP上浏览ppt,初步方案是ppt转为图片。

实现

1、ppt转为pdf,然后pdf转为图片

该种实现,先将ppt转为pdf文件,实现方式有很多,可参考之前文章 文档在线预览,将文档转为pdf

然后实现将pdf转为图片,实现方式有很多,这里介绍其中一种, apache pdfbox ,具体如下:

maven依赖:

            <dependency><groupId>org.apache.pdfbox</groupId><artifactId>fontbox</artifactId><version>2.0.12</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.12</version></dependency>

java代码:

        try {int dpi = 296;PDDocument pdDocument = PDDocument.load(new File("pdf file path"));PDFRenderer renderer = new PDFRenderer(pdDocument);int pageCount = pdDocument.getNumberOfPages();/* dpi越大转换后越清晰,相对转换速度越慢 */for (int i = 0; i < pageCount; i++) {File dstFile = new File("png file path");BufferedImage image = renderer.renderImageWithDPI(i, dpi);ImageIO.write(image, "png", dstFile);}}catch (Exception e){e.printStackTrace();}

转换之后,可自行添加finally对资源进行处理

2、利用apache poi直接将ppt转为图片

上述方案中,有两步实现,先转pdf,再转图片。转pdf方案中,比较靠谱快速的方法可能需要依赖外部 liberoffice 或者 openoffice. 实现ppt预览,也可通过apache poi 将ppt直接转为图片

apache poi提供丰富的office操作api,可直接通过java代码读写操作excel sheet,表格,内容等。也可以直接操作ppt slider,插入,读取内容等。

talk is cheap, show my code

maven 依赖:

            <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${appache.poi.version}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${appache.poi.version}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>${appache.poi.version}</version></dependency>

官方最新版本已经到了 4.0.0

由于 powrpoint 有ppt和pptx(office 2007之后) ,ppt文件本质是二进制文件,而pptx 是xml 。所以需要不同的处理。具体实现如下:

ppt,使用HSLFSlide 读取

        FileInputStream is = new FileInputStream("ppt file path");HSLFSlideShow ppt = new HSLFSlideShow(is);Dimension pageSize = ppt.getPageSize();int idx = 1;try {for (HSLFSlide slide : ppt.getSlides()) {toPNG(pageSize.getWidth(), pageSize.getHeight(), slide);idx++;}} catch (Exception e) {throw e;} finally {if (is != null) {is.close();}if (ppt != null){ppt.close();}}

pptx 使用XSLF

        FileInputStream is = new FileInputStream("pptx file path");XMLSlideShow pptx = new XMLSlideShow(is);Dimension pageSize = pptx.getPageSize();int idx = 1;try {for (XSLFSlide xslfSlide : pptx.getSlides()) {this.toPNG(pageSize.width, pageSize.height, xslfSlide );idx++;}} catch (Exception e) {throw e;} finally {if (is != null){is.close();}if (pptx != null){pptx.close();}}

topng 实现:

//image_rate 图片尺寸倍率,rate越大,图片越清晰,转换时间越长int imageWidth = (int) Math.floor(image_rate * pageSize.width);int imageHeight = (int) Math.floor(image_rate * pageSize.height);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);// clear the drawing areagraphics.setPaint(Color.white);graphics.fill(new Rectangle2D.Float(0, 0, imageWidth, imageHeight));graphics.scale(this.IMAGE_RATE, this.IMAGE_RATE);FileOutputStream out = null;try {xslfSlide.draw(graphics);out = new FileOutputStream(new File("png file path"));javax.imageio.ImageIO.write(img, "png", out);} catch (IOException ioe) {ioe.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {try {if (out != null) {out.flush();out.close();}} catch (IOException ioe) {ioe.printStackTrace();}if (graphics != null){graphics.dispose();}if (img != null){img.flush();}}

这样能初步实现ppt转图片,实际过程中有如下几个问题:

1、中文 问题: 如果在本地测试觉得一切ok,那么部署到测试环境或者线上就可能出现中文乱码问题。

原因可能是ppt内容中字体不支持,服务器未安装中文字体。 如linux上,可 通过 fc-list :lang=zh 查看。

如果未安装,可通过 yum -y install fontconfig 安装,然后在/usr/share 目录下会发现 fonts目录,下载中文字体如:heiti.ttf

拷贝到fonts目录下,chmod 赋权限。再次执行 fc-list :lang=zh 命令,显示如下,则表示安装成功,也可以安装宋体等其他字体

如果是docker环境,则可将上述安装步骤写入到dockerfile中。

安装完成字体后,代码中设置字体如下:

ppt:

            for (HSLFShape shape : slide.getShapes()) {if (shape instanceof HSLFTextShape) {HSLFTextShape sh = (HSLFTextShape) shape;List<HSLFTextParagraph> textParagraphs = sh.getTextParagraphs();for (HSLFTextParagraph hslfTextParagraph : textParagraphs) {List<HSLFTextRun> textRuns = hslfTextParagraph.getTextRuns();for (HSLFTextRun hslfTextRun : textRuns) {hslfTextRun.setFontFamily("宋体");hslfTextRun.setFontIndex(1);}}}}

pptx:

               for (XSLFShape shape : slide.getShapes()){if (shape instanceof XSLFTextShape){XSLFTextShape sh = (XSLFTextShape) shape;List<XSLFTextParagraph> textParagraphs = sh.getTextParagraphs();for (XSLFTextParagraph xslfTextParagraph : textParagraphs) {List<XSLFTextRun> textRuns = xslfTextParagraph.getTextRuns();for (XSLFTextRun xslfTextRun : textRuns) {xslfTextRun.setFontFamily("宋体");}}}}

经上述操作,中文问题基本能解决了

2、如果pptx文件中含有嵌入文件,即在ppt中插入外部文件,可能会报错:

java.lang.ArrayStoreExceptionat java.lang.System.arraycopy(Native Method)at org.apache.xmlbeans.impl.values.XmlObjectBase._typedArray(XmlObjectBase.java:409)at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:457)at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:415)at org.apache.poi.xslf.usermodel.XSLFDrawing.<init>(XSLFDrawing.java:44)at org.apache.poi.xslf.usermodel.XSLFSheet.initDrawingAndShapes(XSLFSheet.java:201)at org.apache.poi.xslf.usermodel.XSLFSheet.getShapes(XSLFSheet.java:188)at org.apache.poi.sl.draw.DrawSheet.draw(DrawSheet.java:55)at org.apache.poi.sl.draw.DrawSlide.draw(DrawSlide.java:41)at org.apache.poi.xslf.usermodel.XSLFSlide.draw(XSLFSlide.java:307)

ppt文件不会有该问题,主要是上文中提到,pptx 可解析为xml文件,解析为XmlObject 时,类型转换错误,

XmlObjectBase中:
System.arraycopy(input, 0, result, 0, input.length);

debug源码发现,input 数组,三个元素类型不同,如下:

至于完整的pptx文件解析后的xml文件,有兴趣的同学可以自己看看,这里就不贴出来了。

百思不得其姐,一度想 通过 poi remove掉这个文件,发现事情没那么简单,然后准备祈祷不要有嵌入文件的pptx时,发现有一老哥和我一样的问题,参考:可能需要翻墙

原来是其他pom引入中含有xmlbeans 2.3 版本 。

解决办法是确保xmlbeans 版本到2.6 。希望有老哥遇到该问题时能解决,找到依赖源, exclusion 一下。

3、转换慢,OOM等问题

由于转换是ppt的每一页进行单独转换,如果ppt页数多,可能会慢。 解决办法,一种是减小上文中的image_rate,如设置为1.

还有就是可以通过多线程并发转换,但是由于该转换操作是CPU密集型操作,所以需要根据机器性能决定。具体代码如下:

            for (XSLFSlide slide : ppt.getSlides()) {CompletableFuture<byte[]> future = CompletableFuture.supplyAsync(() -> toPNG(pgsize.width, pgsize.height, slide, targetType), workers).handle((targetFilePath, e) -> {if (e != null) {logger.error("covertPPTX error", e);return null;} else {return targetFilePath;}});resultMap.put(idx, future);idx++;}

方式有很多种

并发转换时,一定要注意资源的释放,否则会容易出现OOM。

后记

本文主要是开发过程中问题记录,比较繁杂,参考了官网及一些博客,如有侵权,立马删除。

PPT在线预览 转换为图片实现方案 Apache POI 实现时踩坑:含嵌入文件ppt转换报错 ArrayStoreException相关推荐

  1. poi PPT 在线预览

    web 中在线预览office 是个头疼的问题. 今天项目刚好做完一个PPT在线预览的功能   在这里分享给大家   思路:      获取网络PPT 文件 将PPT每一页的幻灯片都转换成单张图片   ...

  2. JavaScript实现Word、Excel、PPT在线预览

      在项目中前端需要根据后台返回的文件地址实现在线预览,图片.视频.pdf等格式的文件用 window.open(url) 或 window.location.href=url 能够实现在线预览,但W ...

  3. Spring Boot整合OpenOffice实现Word、Excel、PPT在线预览

    Spring Boot整合OpenOffice实现Word.Excel.PPT在线预览 1 介绍下OpenOffice 官网:https://www.openoffice.org/download/ ...

  4. pdf,word,ppt在线预览

    pdf,word,ppt在线预览 先展示下效果 pdf跟ppt的预览效果: word的预览效果 实现过程-只需一个iframe标签即可 详细介绍请看这里 <iframe src="ht ...

  5. 实现PPT在线预览,PPT转图片方案

    一.PPT转图片可行方案探索历程 PPT转图片方案 方案具体步骤及分析 已放弃方案 poi(失真度太高):Aspose直接转图片(收费,效果较好,备选):微软Office Online(需要基于Win ...

  6. 文档在线预览(四)使用js前端实现word、excel、pdf、ppt 在线预览

    文章目录 实现方案 一.docx文件实现前端预览 1.docx-preview 2.Mammoth 二.PDF文件实现前端预览 1.pdf.js 2.pdfobject.js 3.vue-pdf 4. ...

  7. PDF在线预览插件汇总与方案总结

    先介绍下工作背景: java一枚,最近在做政府单位的信息管理软件,后台需要对数据进行汇总,并生成PDF格式的报告文件,生成PDF文件用的是iReport生成的,具体可以去百度.生成完之后客户得查看吧, ...

  8. WEB在线预览PDF,WORD方案总结

    好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受. 目录 一.PDF的预览方式 1.PDFObject 2.PDF.JS 3.jsPDF 4.jQuery Media ...

  9. html在线预览ppt excel,JavaScript实现Word、Excel、PPT在线预览

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_27626333/article/ ...

最新文章

  1. 给动态生成的按钮添加ajax,Ajax/Javascript动态创建按钮的问题
  2. klib库下的kroundup32(二进制的四舍五入)算法
  3. 电脑技巧:如何开机进入纯净的Windows系统,看完你就会了!
  4. 会话跟踪之Session
  5. pythondocumentation是什么_怎样阅读Python官方文档
  6. 大数据学习(08)--Hadoop中的数据仓库Hive
  7. python groupby_用python自动生成全校学生成绩报告
  8. MyBatis学习总结(24)——Mybatis常见问题汇总
  9. wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示...
  10. 借助excel工具进行多元线性回归模型的建立及案例分析
  11. Postgresql数据库介绍15——客户端认证
  12. 【PPT技巧】为PPT寻找好看的英文字体(English nice-looking font free)并安装到Windows
  13. 最全的人力资源行业精美报表模板,免费下载啦
  14. 数据仓库和数据挖掘基础知识点
  15. python3代码换行与不换行问题
  16. 【官网】飞腾 2000 处理器
  17. 制作视频软件哪个好?教培人最爱的视频制作软件,一款就够!
  18. Excel:宏运行打开新表后excel崩溃
  19. java 首字母转小写
  20. 安装 Ubuntu (乌班图)

热门文章

  1. 一个java随机数据的工具类
  2. Flutter Widget嵌套深,修改代码麻烦?
  3. Pascal's Triangle帕斯卡三角形算法
  4. 博通二合一蓝牙android驱动,Broadcom 博通 蓝牙与无线网卡一体-蓝牙3.0版驱动 for xp...
  5. linux导出文件夹到u盘,把Linux系统放在U盘上直接在U盘上运行Linux
  6. 卡巴斯基KAV/KIS 6.0/7.0 授权许可文件永久免费更新方法
  7. 小明一共看了多少朵不同的花儿
  8. matlab 信号插零,【 MATLAB 】MATLAB 实现模拟信号采样后的重建(二)零阶保持(ZOH)...
  9. 什么样性格的人适合科研_什么性格的人更容易得癌症?科学研究这么看
  10. 吉林大学软件学院《软件项目管理》课程重点与测试题 第十一章 评审