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

2023-12-26 20:36:10

目录

项目需求

后端接口实现

1、引入poi依赖

2、代码编写

1、controller

2、service层

测试出现的bug

小结


项目需求

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

后端接口实现

1、引入poi依赖

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

<!-- 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文件对象

代码示例:

@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,最后记得关闭不用的对象,回收一下内存。

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);
    }
 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是这个需求最好的处理对象,是不是还有更好的处理方式。

文章来源:https://blog.csdn.net/a2285786446/article/details/135220076
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。