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

news2024/11/20 7:23: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是这个需求最好的处理对象,是不是还有更好的处理方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1337821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Servlet见解2

4 创建servlet的三种方式 4.1 实现Servlet接口的方式 import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException;WebServlet("/test1") public class Servlet1 implements Servlet {Overridepublic void init(ServletConf…

alertmanage调用企业微信告警(k8s内部署)

一、前言 alertmanage调用企业微信应用告警会比直接使用钉钉告警更麻烦一点&#xff0c;调用企业微信应用告警需要在应用内配置企业可信ip&#xff0c;不然调用企业微信接口就会报错&#xff0c;提示ip地址有风险 二、部署 先自行创建企业微信&#xff0c;再使用管理后台创建应…

视频遥测终端机的设计需求

目录 1.目的 2.参考文件 3.总体描述 4.硬件资源描述 4.1微控制单元 4.2视频处理单元 4.3性能指标 5.功能要求 5.1系统参数要求 5.1.1系统管理 5.1.2系统配置 5.1.2.1一般参数 5.1.2.2编码参数 5.1.2.3网络参数 5.1.2.4网络服务 5.1.2.5OSD参数 5.1.2.6抓拍 5.…

MYSQL一一约束

概述&#xff1a; ①概念约束是作用于表中字段的规则&#xff0c;用于限制存储在表中的数据 ②目的&#xff1a;保证数据库中的数据的正确性&#xff0c;有效性和完整性 ③分类&#xff1a; 注意&#xff1a;约束是作用于表中字段上的&#xff0c;可以在创建表/修改表的时候…

【C语言】指针详解(四)

目录 1.assert断言 2.指针的使用和传址调用 2.1strlen的模拟使用 2.2传值调用和传址调用 1.assert断言 assert.h头文件定义了宏 assert()&#xff0c;用于在运行时确保程序符合指定条件&#xff0c;如果不符合&#xff0c;就报错终止运行。这个宏常常被称为“断言”。 例如…

主流级显卡的新选择,Sparkle(撼与科技)Intel Arc A750兽人体验分享

▼前言 对于玩家而言&#xff0c;英特尔独显的出现不仅打破了NVIDIA与AMD双雄天下的局面&#xff0c;而且旗下的Arc A系列显卡还拥有不俗的做工性能以及颇具优势的价格&#xff0c;无论是升级或者是装新机都非常合适。如果要在Arc A系列当中选一个性能不俗&#xff0c;能够满足…

从AMI镜像恢复AWS Amazon Linux 2实例碰到的VNC服务以及Chrome浏览器无法启动的问题

文章目录 小结问题及解决VNC服务无法启动Chrome浏览器无法启动 参考 小结 将Amazon Linux 2保存为AMI (Amazon Machine Images)后&#xff0c;恢复成EC2 Instance (实例)后&#xff0c;VNC服务以及Chrome浏览器无法启动&#xff0c;进行了解决。 问题及解决 如果要将一个EC2…

算法训练第四十八天|198. 打家劫舍、213. 打家劫舍 II、337. 打家劫舍 III

198. 打家劫舍&#xff1a; 题目链接 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报…

LSTM中文新闻分类源码详解

LSTM中文新闻分类 一、导包二、读取数据三、数据预处理1.分词、去掉停用词和数字、字母转换成小写等2.新闻文本标签数值化 三、创建词汇表/词典1.data.Field()2.空格切分等3.构建词汇表/词典使用训练集构建单词表&#xff0c;vectorsNone:没有使用预训练好的词向量,而是使用的是…

PyTorch深度学习实战(27)——变分自编码器(Variational Autoencoder, VAE)

PyTorch深度学习实战&#xff08;27&#xff09;——变分自编码器 0. 前言1. 变分自编码器1.1 自编码器的局限性1.2 VAE 工作原理1.3 VAE 构建策略1.4 KL 散度1.5 重参数化技巧 2. 构建 VAE小结系列链接 0. 前言 变分自编码器 (Variational Autoencoder, VAE) 是一种生成模型&…

华为ipv6配置之ospf案例

R1 ipv6 ospfv3 1 router-id 1.1.1.1 //必须要手动配置ospf id&#xff0c;它不会自动生成 interface GigabitEthernet0/0/0 ipv6 enable ipv6 address 2000::2/96 ospfv3 1 area 0.0.0.0 interface LoopBack0 ipv6 enable ipv6 address 2001::1/96 ospfv3 1 area 0.0.0.0 R2…

腾讯云4核8G服务器三年优惠价格表

腾讯云轻量服务器4核8G12M有三年优惠价吗&#xff1f;有&#xff0c;但是不怎么优势&#xff0c;相对于云轻量2核2G4M带宽三年价格是540元、2核4G5M带宽3年优惠价756元&#xff0c;4核8G12M轻量应用服务器三年价格是5292元&#xff0c;怎么样&#xff1f;还想买吗&#xff1f;阿…

文件夹共享功能的配置 以及Windows server2012防火墙的配置

目录 一. 配置文件夹共享功能 1.1 为什么需要配置文件夹共享功能 1.2 配置文件夹共享 1.3 访问共享文件夹 1.4 配置取消 用户名和密码认证 二. windows server 2012防火墙配置 思维导图 一. 配置文件夹共享功能 1.1 为什么需要配置文件夹共享功能 我们在工作和生活中经…

设计模式-单例模式(结合JVM基础知识)

1.定义介绍 所谓单例模式&#xff0c;是指在程序运行时&#xff0c;整个JVM中只有一个该类的实例对象 2. 单例模式的优点 复用性高&#xff0c;节省内存资源。类的加载、连接、初始化、使用都要占用虚拟机内存空间&#xff0c;因此&#xff0c;频繁创建对象会造成资源浪费&a…

【Linux基础】6. 进程管理工具

文章目录 【 1. 查询进程 】【 2. 终止进程 】【 3. top 进程监控 】【 4. pmap 分析线程栈 】【 5. 综合运用 】 任何进程都与文件关联&#xff1b;我们会用到 lsof 工具&#xff08;list opened files&#xff09;&#xff0c;作用是列举系统中已经被打开的文件。在 linux环境…

TG7050CKN,TG7050SKN ,TG7050CMN,TG7050SMN

爱普生推出的温补晶振型号&#xff1a;TG7050CKN&#xff0c;TG7050SKN &#xff0c;TG7050CMN&#xff0c;TG7050SMN频率范围为 10mhz ~ 54mhz 适用于广泛的频率需求。这几款的特点就是耐高温&#xff0c;温度可达105℃高温&#xff0c;而且都是高稳定性温补晶振&#xff0c;&…

[足式机器人]Part2 Dr. CAN学习笔记-Ch00 - 数学知识基础

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Ch00 - 数学知识基础 1. Ch0-1矩阵的导数运算1.1标量向量方程对向量求导&#xff0c;分母布局&#xff0c;分子布局1.1.1 标量方程对向量的导数1.1.2 向量方程对向量的导数 1.2 案例分析&#xf…

目标检测-Two Stage-SPP Net

文章目录 前言一、SPP Net 的网络结构和流程二、SPP的创新点总结 前言 SPP Net&#xff1a;Spatial Pyramid Pooling Net&#xff08;空间金字塔池化网络&#xff09; SPP-Net是出自何凯明教授于2015年发表在IEEE上的论文-《Spatial Pyramid Pooling in Deep ConvolutionalNetw…

从企业级负载均衡到云原生,深入解读F5

上世纪九十年代&#xff0c;Internet快速发展催生了大量在线网站&#xff0c;Web访问量迅速提升。在互联网泡沫破灭前&#xff0c;这个领域基本是围绕如何对Web网站进行负载均衡与优化。从1997年F5发布了BIG-IP&#xff0c;到快速地形成完整ADC产品线&#xff0c;企业级负载均衡…

阿里云自建官方Docker仓库镜像提交拉取方法

文章目录 发布镜像到DockerHub发布镜像到自建Docker仓库(Harbor)修改配置文件在Linux服务器中登录Docker打TAGPUSH提交镜像PULL拉取镜像 发布镜像到阿里云容器服务在Linux服务器中登录DockerPUSH提交镜像PULL拉取镜像 发布镜像到DockerHub 本地我们镜像命名可能会不规范&#…