使用poi将pptx文件转为图片详解

目录

项目需求

后端接口实现

1、引入poi依赖

2、代码编写

1、controller

2、service层

测试出现的bug

小结


项目需求

前端需要上传pptx文件,后端保存为图片,并将图片地址保存数据库,最后大屏展示时显示之前上传的pptx的图片。需求看上去是简单的,简单聊一下,不管是使用vue的elementui还是传统的layui都有很好的实现组件,这里我们重点不在前端,所以不去细说,感兴趣的同学可以了解一下。

后端接口实现

1、引入poi依赖

这里我使用的是最新的依赖,大家想要稳定一点可以用4.1.2的版本

java 复制代码
<!-- excel解析工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.4</version>
        </dependency>

2、代码编写

一般工作中,后端都是提供接口给前端访问的,项目会有一定的分层

1、controller

我们主要用来接受参数,然后把参数带到service层去处理业务逻辑就行

这里我们需要接受的前端参数有2个:

MultipartFile:pptx文件对象

代码示例:

java 复制代码
@ResponseBody
@RequestMapping("/admin/pheno/material/caseContentPhotoUpload")
    public ResultJson caseContentPhotoUpload(MultipartFile file, HttpServletRequest request) {
        return ResultJson.build(pheContentService.caseContentPhotoUpload(file,request));
    }

2、service层

实际的业务代码编写,代码逻辑是比较简单的,先获取文件的输入流,将文件输入流转化为xmlslideshow()对象,这个就是poi的处理pptx文件的工具包了,在里面循环操作每一张pptx。pptx文件也就是xml文件,所以是用这个处理的,然后就是保存图片了,思路就是建一张画布,将文件画上去,最后保存到对应路径,本地数据库啥的。非常简单。IMAGE_SCALE 是一个常量,我给的是8,最后记得关闭不用的对象,回收一下内存。

java 复制代码
public ResultService caseContentPhotoUpload(MultipartFile file, HttpServletRequest request) {
        String serverPath=request.getSession().getServletContext().getRealPath("/");
        ArrayList<Object> outPathUrlList = new ArrayList<>();
        InputStream is = null;
        XMLSlideShow ppt = null;
        try {
            is = file.getInputStream();
            ppt =new XMLSlideShow(is);
            Dimension pgSize = ppt.getPageSize();
            for (XSLFSlide slide : ppt.getSlides()) {

                for(XSLFShape shape : slide.getShapes()){

                    if(shape instanceof XSLFTextShape) {

                        XSLFTextShape tsh = (XSLFTextShape)shape;

                        for(XSLFTextParagraph p : tsh){

                            for(XSLFTextRun r : p){

                                r.setFontFamily("宋体");

                            }

                        }

                    }
                }

                String url = toPNG(pgSize.width, pgSize.height, slide,serverPath,hrStaffSession);
                outPathUrlList.add(url);
            }
        } catch (IOException e) {
            log.debug("ppt转换图片失败,{}"+ e.getMessage());
            throw new RuntimeException("ppt转换图片失败" + e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (ppt != null) {
                    ppt.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResultService.buildSuccess(outPathUrlList);
    }
java 复制代码
 protected String toPNG(int pgWidth, int pgHeight, XSLFSlide slide, String serverPath, HrStaffSession hrStaffSession) throws IOException {
        int imageWidth = (int) Math.floor(IMAGE_SCALE * pgWidth);
        int imageHeight = (int) Math.floor(IMAGE_SCALE * pgHeight);
        ResultService resultService =null;
        BufferedImage img = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = img.createGraphics();
        graphics.setPaint(Color.white);
        graphics.fill(new Rectangle2D.Float(0, 0, pgWidth, pgHeight));
        graphics.scale(IMAGE_SCALE, IMAGE_SCALE);
        slide.draw(graphics);
       
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            bos = new ByteArrayOutputStream();
            ImageIO.write(img, "png", bos);
            InputStream input = new ByteArrayInputStream(bos.toByteArray());
            MultipartFile multipartFile = getMultipartFile(input,"ppt图片.png");
            input.close();
            resultService = fileService.fileUpload(multipartFile, serverPath, hrStaffSession);
        } finally {
            bos.close();
        }
        SystemFileVO systemFileVO=(SystemFileVO)resultService.getObject();
        return systemFileVO.getThumbPath();
    }

测试出现的bug

不知道是poi对于pptx做的兼容不好还是啥原因,总之有很多的问题

1、文字问题,pptx使用的都是微软雅黑,但是转为图片时,文字会有溢出和下坠的变化,

所以我从4.1.2的包切到了新版本的5.2.0,解决了文字的溢出问题,然后我将微软雅黑统一设置成宋体,在window上是解决了,但是在linux上展现效果又有一定的差异,总的来说是解决了。

2、段落的首行缩进混乱,设置了首行缩进,但是缩进去了一行的最后面

最后只能不要这个样式,去手动添加空格

3、一些图标无法读取,当图标是组合式也就是拼接的时候,会出现读取不了的情况,也只能在写pptx的时候规避一下

4、在不同操作系统上展现效果有细微区别,测试也比较麻烦

。。。

小结

感觉在技术的选取上应该再参考一下,是否poi是这个需求最好的处理对象,是不是还有更好的处理方式。

相关推荐
Kun_Guan1 天前
接IT方案编写(PPT/WORD)、业务架构设计、投标任务
powerpoint
诸葛大钢铁2 天前
PDF转PPT转换方法总结
pdf·powerpoint
迪娜学姐2 天前
GenSpark vs Manus实测对比:文献综述与学术PPT,哪家强?
论文阅读·人工智能·prompt·powerpoint·论文笔记
skywalk81632 天前
市面上哪款AI开源软件做ppt最好?
人工智能·powerpoint
阿幸软件杂货间3 天前
PPT转图片拼贴工具 v3.0
python·opencv·计算机视觉·powerpoint
阿幸软件杂货间3 天前
PPT转图片拼贴工具 v1.0
python·powerpoint
阿幸软件杂货间4 天前
PPT转图片拼贴工具 v2.0
android·python·powerpoint
阿幸软件杂货间4 天前
PPT转图片拼贴工具 v4.3
python·powerpoint
MiaoChuPPT4 天前
秒出PPT正式改名秒出AI,开启AI赋能新体验!
人工智能·powerpoint
AIcailiaoxing9 天前
ai工具集:AI材料星ppt生成,让你的演示更出彩
人工智能·powerpoint