基于PIO把带有数据和图片的excel表导入到数据库中(图片存储到服务器中,可访问图片路径存入在数据库中)

2023-11-02

基于PIO把带有数据和图片的excel表导入到数据库中(图片存储到服务器中,可访问图片路径存入在数据库中)



前言

创作来之不易可点一颗小心心

一、工具类getExcelMap说明?

以下工具类都是基于PIO原生态实现的,其中包含了.xls和.xlsx的导入,也涉及到了在excel解析图片。

二、使用步骤

1.引入库

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>

2.方法实现:importFile

    public void importFile(MultipartFile file) {

        Map<String, String> fieldMap=new HashMap<>();
        fieldMap.put("id", "id");
        fieldMap.put("姓名", "name");
        fieldMap.put("年龄", "age");
        fieldMap.put("性别", "sex");
        fieldMap.put("电话", "phone");
        fieldMap.put("人物肖像", "photo");
        fieldMap.put("身份证信息", "message");

        //图片存储路径
        String filePath="D://cs/picture/web/";
        //图片访问地址
        String webPath="http://localhost:8080/cccc/pic/";
        List<Map<String,Object>> list=  getExcelMap(file,fieldMap, filePath,webPath);
    }

3.读excel中的数据和图片

excel截图:在这里插入图片描述

代码如下:

/**
* fieldMap:字段信息
* filePath 为图片的存储路径:/aaa/bbb/。
* webPath 为图片的访问路径:http://localhost:8080/aaa/bbb/
* 
*/
public List<Map<String,Object>> getExcelMap(MultipartFile multipartFile,Map<String, String> fieldMap,String filePath,String webPath ) {
        List<Map<String,Object>> list=new ArrayList<>();
        //如果excel表中有日期的话,则把日期规范化
        DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try (InputStream inputStream = multipartFile.getInputStream()) {
            //读取excel
            Workbook workbook;
            Map<String, PictureData> sheetPictures=null;
            Sheet sheet=null;
            if (multipartFile.getOriginalFilename().endsWith(".xls")) {
                workbook = new HSSFWorkbook(inputStream);
                sheet= workbook.getSheetAt(0);
                //获取图片
                sheetPictures = ExcelUtil.getPictures((HSSFSheet)sheet);
            } else {
                workbook = new XSSFWorkbook(inputStream);
                sheet= workbook.getSheetAt(0);
                //获取图片
                sheetPictures = ExcelUtil.getPictures((XSSFSheet) sheet);
            }
            Map<String,String> printImgMap=null;
            //把图片存入服务器中,返回图片存储路径 printImgMap
            if (sheetPictures.size()!=0){
                printImgMap= ExcelUtil.printImg( sheetPictures,filePath,webPath);
            }

            //获取的firstRowNum其实是=0的,firstCellNum 也是=0
            int firstRowNum = sheet.getFirstRowNum();
            Row firstRow = sheet.getRow(firstRowNum);
            int lastRowNum = sheet.getLastRowNum();
            int firstCellNum = firstRow.getFirstCellNum();
            int lastCellNum = firstRow.getLastCellNum();
            //firstRowNum + 1是因为单元格都是坐标(0,0)开始算的。excel表中的第一行是表头,所以不需要获取,就直接从第二行数据行开始
            for (int i = firstRowNum + 1; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
               //空表格就不需要进循环了,根据第一列名称的有无来判断是否是空白行
               /**
                * formatter.formatCellValue(row.getCell(0))这个方法就相当于:
                * Cell cell = row.getCell(0);
               	* cell.setCellType(CellType.STRING);
                * value = cell.getStringCellValue();
               	*/
                DataFormatter formatter = new DataFormatter();
                if (StringUtil.isBlank(formatter.formatCellValue(row.getCell(0)))){
                    break;
                }
                String value = "";
                Map<String,Object> map=new LinkedHashMap<>();
                log.info("lastCellNum------>{}",lastCellNum);
                for (int j = firstCellNum; j < lastCellNum; j++) {
                    value = "";
                    Cell cell = row.getCell(j);
					//null != cell避免遇到空指针。使用StringUtil.isNotBlank(cell)的话会报错,原因是如果单元格没有内容的话会报空指针异常。
                    if(null != cell) {
                        log.info("第【{}】行,第【{}】列数据:{}", i, j, cell);
                        //单元格为整数、小数、日期
                        if (cell.getCellType().equals(CellType.NUMERIC)) {
                            if (DateUtil.isCellDateFormatted(cell)) {
                                Date d = cell.getDateCellValue();
                                value = formater.format(d);
                            } else {
                                cell.setCellType(CellType.STRING);
                                value = cell.getStringCellValue();
                            }
                         //单元格中有图片存在
                        }else if(StringUtil.isNotBlank(printImgMap.get(i + "_" +j))){
                            value=printImgMap.get(i+"_"+j);
                        } else {
                            cell.setCellType(CellType.STRING);
                            value = cell.getStringCellValue();
                        }
                    }
					//遍历列,获得第一行对应的表头所在列的单元格中的字段中文名称。然后根据字段中文名获取到字段英文名。为key值。
                    Cell headCell = firstRow.getCell(j);
                    log.info("headCell[{}]:{}", j, headCell);
                    String fieldNameCn = headCell.getStringCellValue();
                    log.info("fieldNameCn:{}", fieldNameCn);
                    String fieldNameEn = fieldMap.get(fieldNameCn);
                    log.info("fieldNameEn:{}", fieldNameEn);
                    map.put(fieldNameEn,value);
                    log.info("map:{}",map);
                }
                list.add(map);
            }
        } catch (IOException e) {
            log.error("拼接sql发生异常 [{}]", e);
        }
        return list;
    }

4.ExcelUtil:获取图片和存图片

public class ExcelUtil{

 /**  支持单个图片
     * 获取Excel2003图片
     * @param sheet 当前sheet对象
     * @return Map key:图片单元格索引(0_11)String,value:图片流PictureData
     * @throws IOException
     */
    public static Map<String, PictureData> getPictures(HSSFSheet sheet) {
        Map<String, PictureData> map = new HashMap<>();
        List<HSSFShape> list = sheet.getDrawingPatriarch().getChildren();
        for (HSSFShape shape : list) {
            if (shape instanceof HSSFPicture) {
                HSSFPicture picture = (HSSFPicture) shape;
                HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();
                PictureData pData = picture.getPictureData();
                String key = cAnchor.getRow1() + "_" + cAnchor.getCol1();
                map.put(key, pData);
            }
        }
        return map;
    }

    /**
     * 获取图片和位置 (xlsx)
     * @param sheet
     * @return Map key:图片单元格索引(0_1)String,value:图片流PictureData
     * @throws IOException
     */
    public static Map<String, PictureData> getPictures (XSSFSheet sheet) throws IOException {
        Map<String, PictureData> map = new HashMap<>();
        for (POIXMLDocumentPart dr : sheet.getRelations()) {
            if (dr instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) dr;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    XSSFPicture pic = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = (XSSFClientAnchor) shape.getAnchor();
                    CTMarker ctMarker = anchor.getFrom();
                    String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
                    map.put(picIndex, pic.getPictureData());
                }
            }
        }
        return map;
    }


 /**
     * 图片写出 
     * @param mapList为图片对象
     * @param webPath 为图片的访问路径:http://localhost:8080/aaa/bbb/
     * @param filePath 为图片的存储路径:/aaa/bbb/。
     * @throws IOException
     */

    //图片写出
    public static Map printImg(Map<String, PictureData> mapList,String filePath,String webPath) throws IOException {
        Map<String, String> map = new HashMap<>();
        mapList.forEach((key, pic) -> {
            // 文件扩展名
            String ext = pic.suggestFileExtension();
            // 图片数据
            byte[] data = pic.getData();
            //图片保存路径 医院名称+微信公众号/医院照片+图片后缀
            String ImgName= UUID.randomUUID().toString()+"." + ext;
            //写入到对应的文件夹路径下面去
            //filePath+imgName=/aaa/bbb/xxxxx.jpg
            try (FileOutputStream out = new FileOutputStream(filePath+imgName)) {
            out.write(bytes);
        	} catch (Exception e) {
            e.printStackTrace();
        	}
        	//map中的value为:http://localhost:8080/aaa/bbb/xxxxx.jpg
            map.put(key, webPath+ImgPath);
            });
            return map;
        }

    }


}

5.导入报错

有一天,导入未带图片的.xlsx表单,报以下错误:
XSSFSimpleShape cannot be cast to org.apache.poi.xssf.usermodel.XSSFPicture

1.原因是:低版本改成了高版本Excel,解析有问题
  解决办法:将【xlsx】另存为【xls】
 
2.报错显示的是类型转换错误,我明明是用XSSFShape类型转换的,XSSFShapeGroup是那来的?在网上查到XSSFShapeGroup是获取组合形状的。
  解决办法:在excel表里面找到组合形状的图形,取消组合

3.原因是:默认导入包含矩形形状表格时出错,代码在获取所有图片的时候把所有Shape强转成XSSFPicture,实际上是XSSFSimpleShape,强制失败
在ExcelUtil:获取图片和存图片的代码14行出现问题。
  解决办法:
  List<XSSFShape> shapes = drawing.getShapes();
  替换成
  	 List<XSSFShape> shapes = drawing.getShapes()
                        .stream().filter(s->s instanceof XSSFPicture).collect(Collectors.toList());

总结

由于List<Map<String,Object>> getExcelMap最后的返回list存入数据库去的方式是使用jdbc原生态insert语句拼接而成的,过程很复杂,但其核心取excel中的数据和图片已实现

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于PIO把带有数据和图片的excel表导入到数据库中(图片存储到服务器中,可访问图片路径存入在数据库中) 的相关文章

  • 如何在测试套件中定义 JUnit 方法规则?

    我有一个类 它是 JUnit 测试类的 JUnit 套件 我想定义一个规则on the suite 这是可以做到的 但需要做一些工作 您还需要定义自己的 Suite 运行程序和测试运行程序 然后在测试运行程序中重写 runChild 使用以
  • Spring控制器是线程安全的吗

    我遇到了这个控制器示例 想知道它是否是线程安全的 我特别想知道 gson 实例变量 import org springframework stereotype Controller import org springframework we
  • 检查双精度值的等于和不等于条件

    我在比较两者时遇到困难double values using and 我创建了 6 个双变量并尝试进行比较If健康 状况 double a b c d e f if a b c d e f My code here in case of t
  • 如何对 IntStream 进行逆序排序

    我正在使用 txt 文件读取数字BufferedReader 我想颠倒该流中元素的顺序 以便在收集它们时 它们将从最高到最低排列 我不想在构建数组后进行排序 因为我不知道其中可能有多少元素 我只需要最高的 N 个元素 in new Buff
  • 如何解决 onEditCommit 事件上的类型不匹配错误?

    我在 Fxml 中使用 onEditCommit 事件在用户编辑数据后检索数据 FXML 代码
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • 使用 Java 在浏览器中下载 CSV 文件

    我正在尝试在 Web 应用程序上添加一个按钮 单击该按钮会下载一个 CSV 文件 该文件很小 大小仅约 4KB 我已经制作了按钮并附加了一个侦听器 文件也准备好了 我现在唯一需要做的就是创建单击按钮时下载 csv 文件的实际事件 假设 fi
  • 使用 java 按电子邮件发送日历邀请

    我正在尝试使用 java 发送每封电子邮件的日历邀请 收件人收到电子邮件 但不会显示接受或拒绝的邀请 而是将该事件自动添加到他的日历中 我正在使用 ical4j jar 构建活动 邀请 private Calendar getInvite
  • 尝试在没有 GatewayIntent 的情况下访问消息内容

    我希望每当我写一条打招呼的消息时 机器人都会在控制台中响应一条消息 但它只是给我一个错误 JDA MainWS ReadThread WARN JDA Attempting to access message content without
  • 覆盖 MATLAB 默认静态 javaclasspath 的最佳方法

    MATLAB 配置为在搜索用户可修改的动态路径之前搜索其静态 java 类路径 不幸的是 静态路径包含相当多非常旧的公共库 因此如果您尝试使用新版本 您可能最终会加载错误的实现并出现错误 例如 静态路径包含 google collectio
  • 从 Java 日历迁移到 Joda 日期时间

    以前 当我第一次设计股票应用相关软件时 我决定使用java util Date表示股票的日期 时间信息 后来我体会到了大部分方法java util Date已弃用 因此 很快 我重构了所有代码以利用java util Calendar 然而
  • 使用 Java 从 S3 上的文件在 S3 上创建 zip 文件

    我在 S3 上有很多文件 需要对其进行压缩 然后通过 S3 提供压缩文件 目前 我将它们从流压缩到本地文件 然后再次上传该文件 这会占用大量磁盘空间 因为每个文件大约有 3 10MB 而且我必须压缩多达 100 000 个文件 所以一个 z
  • 如何在android sdk上使用PowerMock

    我想为我的 android 项目编写一些单元测试和仪器测试 然而 我遇到了一个困扰我一段时间的问题 我需要模拟静态方法并伪造返回值来测试项目 经过一些论坛的调查 唯一的方法是使用PowerMock来模拟静态方法 这是我的 gradle 的一
  • 阻止 OSX 变音符号为所有用户禁用 Java 中的 KeyBindings?

    注 我知道这个问题 https stackoverflow com questions 40335285 java keybinds stop working after holding down a key用户必须输入终端命令才能解决此问
  • 来自客户端的超时 Web 服务调用

    我正在使用 RestEasy 客户端调用网络服务 一项要求是 如果调用运行时间超过 5 秒 则中止 超时调用 我如何使用 RestEasy 客户端实现这一目标 我只看到服务器端超时 即如果在一定时间内未完成请求 Rest Easy 网络服务
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • 从一个文本文件中获取数据并将其移动到新的文本文件

    我有一个文件 里面有数据 在我的主要方法中 我读入文件并关闭文件 我调用另一种方法 在原始文件的同一文件夹内创建一个新文件 所以现在我有两个文件 原始文件和通过我调用的方法生成的文件 我需要另一种方法 从原始文件中获取数据并将其写入创建的新
  • 如何将实例变量传递到 Quartz 作业中?

    我想知道如何在 Quartz 中外部传递实例变量 下面是我想写的伪代码 如何将 externalInstance 传递到此作业中 public class SimpleJob implements Job Override public v
  • java中如何找到class文件的包

    我正在编写一个使用 class 文件的 java 程序 我希望能够读取文件系统上的 class 文件 使用 InputStream 并确定它所在的包 该 class 文件可能不在一个好的包目录结构中 它可能位于某个随机位置 我怎样才能做到这

随机推荐

  • open3d显示RGBD点云(rope3d数据集)

    rope3d中同时有深度图 因此 可以创建rgbd图像点云 借助open3d库 需要确定相机内参和外参 注意统一坐标系 例如都显示在world坐标系 usr bin env python3 coding utf 8 for reading
  • 【六】Python全栈之路--for循环

    文章目录 1 双向循环的练习 2 break pass continue的使用 3 for循环 4 小练习 1 双向循环的练习 1 用两个循环完成十行十列的小星星 j 0 while j lt 10 打印星星 i 0 while i lt
  • [MAE]Masked Autoencoders掩膜自编码器

    目录 非对称的编码 解码架构 方法 流程 编码器 解码器 Partial Fine tuning 图像MAE MixMIM Uniform Masking HiViT 视频MAE VideoMAE 多模态MAE M3AE https git
  • v-model支input父子组件传值

    v model用于表单数据的双向绑定 其实它就是一个语法糖 这个背后就做了两个操作 v bind绑定一个value属性 v on指令给当前元素绑定input事件 自定义组件使用v model 应该有以下操作 接收一个value prop 触
  • 线程获取锁的顺序java_多线程(五) java的线程锁

    在多线程中 每个线程的执行顺序 是无法预测不可控制的 那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性 那么如何控制 每个线程对于数据的读写顺序呢 这里就涉及到线程锁 什么是线程锁 使用锁的目的是什么 先看一个例子
  • Linux进程替换

    目录 进程替换 1 定义 2 为什么要进行进程替换 3 怎样进行进程程序替换 4 进程替换的原理 原理总结 5 Linux进程替换的函数 5 1参数 5 2函数返回值问题 5 3 execl函数用例 5 3 2升级案例 编辑 5 3 3调用
  • MySQL的DQL查询语句

    DQL 查询语句 1 排序查询 语法 order by 子句 order by 排序字段1 排序字段2 排序方式 ASC 升序 磨人的 DESC 降序 注意 如果有多个排序条件 则当前面的条件一致时 才会判断第二条件 2 聚合函数 将一列数
  • INS/GNSS组合导航(二)-INS常用的坐标系统及转换

    一 常用坐标系 由于INS是一种完全自主的导航系统 不与外界发生联系 但是我们又想知道物体的的位置 尤其是其与GNSS组合时需要知道其与GNSS在同一坐标系下的位置信息 这就牵扯到了INS的几个导航系统之间的转换 笼统的讲 INS输出的是载
  • springcloud整合consul

    搭建consul环境 linux安装consul 搭建生产者 1 建module provider payment8006 2 写pom
  • electron自动更新

    1 主进程background js引入autoUpdater let autoUpdater require electron updater 2 主进程写入更新代码 if process env WEBPACK DEV SERVER U
  • 图形学实验五曲线生成算法

    实验五 曲线生成算法 实验类型 设计型 实验学时 2实验要求 必修 一 实验目的 了解曲线的生成原理 掌握几种常见的曲线生成算法 利用VC OpenGL实现Bezier曲线生成算法 二 实验内容 1 分析空间曲线生成算法的原理 绘制其程序流
  • 2017年全国大学生电子设计竞赛综合测评题目解析——Multisim仿真

    2017年综合测评仿真电路讲解 题目和结果链接 常用电路Multisim仿真 方波 三角波振荡电路 常用电路Multisim仿真 有源低通滤波器设计 常用电路Multisim仿真 数字芯片74LS74构建分频器设计 常用电路Multisim
  • python 主力资金_真正的主力进场加仓指标源码

    import numpy as np def initialize context g up price 向上碎形最高价 g low price 向下碎形最低价 g up fractal exists 判断有效向上碎形 g down fra
  • Mybatis-Plus学习---(五)灵活使用wapper条件构造器

    手都敲麻了 翻译自官方 条件构造器 说明 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中 例如 query like StringUtils isNotBlank name Entity getN
  • Linux 安装 MariaDB

    CentOS 7 自带的 MariaDB 是 5 5 版本的 使用 yum install mariadb server 命令安装的默认版本是 5 5 的 这是因为系统默认源只有 5 5 的版本 安装准备 检查是否安装过 MariaDB 或
  • MapInfo数据格式

    MapInfo采用双数据库存储模式 即其空间数据与属性数据是分开来存储的 属性数据存储在关系数据库的若干属性表中 而空间数据则以MapInfo的自定义格式保存于若干文件中 二者通过一定的索引机制联系起来 为了提高查询和处理效率 MapInf
  • Octave Convolution[论文详解]

    Drop an Octave Reducing Spatial Redundancy in Convolutional Neural Networks with Octave Convolution github 传统的卷积运算 要成为过去
  • 利用 Transformer 网络建立预测模型

    引言 我最近读了一篇非常有趣的论文 Deep Transformer Models for Time Series Forecasting The Influenza Prevalence Case 我认为这可能是一个有趣的项目 从零开始实
  • 【stm32】串口通信

    串口通信 一 串口通信协议原理 二 usart功能框图 三 stm32库的配置 一 串口通信协议原理 串口在嵌入式系统当中是一类重要的数据通信接口 其本质功能是作为 CPU 和串行设备间的编码转换器 当数据从 CPU 经过串行端口发送出去时
  • 基于PIO把带有数据和图片的excel表导入到数据库中(图片存储到服务器中,可访问图片路径存入在数据库中)

    基于PIO把带有数据和图片的excel表导入到数据库中 图片存储到服务器中 可访问图片路径存入在数据库中 文章目录 基于PIO把带有数据和图片的excel表导入到数据库中 图片存储到服务器中 可访问图片路径存入在数据库中 前言 创作来之不易