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

相关推荐
ms365copilot8 小时前
Copilot生成水果店经营PPT
microsoft·产品运营·powerpoint·copilot
JAVA老架构AI智能化11 小时前
PPT Master Lite — 浏览器端 AI 驱动的 PPT 生成器
人工智能·powerpoint
copilot中国版12 小时前
PowerPoint Copilot内置技能|“优化幻灯片标题”有什么用?
powerpoint·copilot
qq_364682151 天前
汇报材料怎么快速生成PPT?科会通工具实操
powerpoint
言乐61 天前
HTML实现Word、Excel、PPT三种可切换背景,可键盘打字、和像素小人交互
html·word·powerpoint·excel·交互
豆角焖肉1 天前
Apache POI 实现 Excel 上传解析、导出
apache·poi·multipartfile·excel 导入导出·批量导入
copilot中国版3 天前
PPT Copilot 一键统一全篇版式,告别字体混乱、元素错位和重复排版
html·powerpoint·copilot
鲲穹AI种草7 天前
AI 生成 PPT 工具怎么选?鲲穹 PPT 功能实测与横向对比
人工智能·powerpoint
qq_3691736310 天前
一句话将 Word、PPT、PDF 发布成链接
人工智能·pdf·word·powerpoint·效率工具·ai 办公
weixin_4045512414 天前
使用 ZCode 改造 PPT 模板:实践复盘与能力边界
人工智能·powerpoint