EasyExcel3.1.1版本上传文件忽略列头大小写

news2024/12/24 2:37:23

1、背景

项目中使用easyExcel3.1.1版本实现上传下载功能,相关数据DTO以

@ExcelProperty(value = "dealer_gssn_id")

形式规定其每一列的名称,这样的话easyExcel会完全匹配对应的列名,即用户上传文件时,列名写成Dealer_gssn_id,那么对应的DTO不会给对应字段赋值。

现在客户需要实现此项需求,忽略列名大小写,延伸出来以下内容。

2、调研

最开始以为easyExcel有现成的一些方法或者重写类能实现此项功能,但是后来查看源码,发现没办法重写。具体的debug流程不再此细说,主要看一下DefaultAnalysisEventProcessor类:

该类中dealData方法,调用buildHead方法,在该方法中141行使用的equals方法用来比较DTO中value名字与excel上传的列名是否匹配,然而这个类的调用方式是new出来的,这就代表即使我们重写了DefaultAnalysisEventProcessor 类,也没办法执行到我们重写的方法,所以这条路走不通了。

除此之外就只能靠我们自己发散思维去想想该怎么做了。

通过打断点看数据,我们其实能在重写AnalysisEventListener的类中看到invokeHeadMap类中是所有的列头数据,invoke方法中既有列头数据,也有具体的值信息,但是怎么和我们定义的DTO做绑定,这也是个麻烦的事情,可以做,但是想想就比较复杂,可能需要写一大堆的if else,代码也不美观,特别是DTO中字段六七十个,而且不止这一个文件要改,这样做起来麻烦且费时。

那就接着想想其他可能性。

比如在我们上传文件时,在处理数据之前写个公共的util呢?这个util功能会把excel列头拿出来都转化为小写,再重新生成一个MultipartFile文件对象呢?这样,每个上传excel功能我们手动调用一下是不是代码侵入量小一些呢?

所以接下来开始硬刚这部分操作,修修补补,起码能实现上述需求:

这个util可以直接使用,但是每个人场景不同可能需要略微修改,这个util只针对sheet 1中简单的区分列头与数据,比较复杂的excel还需要按实际情况修改:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class FileUtils {

    public static MultipartFile convertToLowerCase(MultipartFile file) throws Exception {
        // 临时存储读取到的数据
        List<List<String>> headerData = new ArrayList<>();
        List<List<String>> rowData = new ArrayList<>();

        // 读取原始文件内容
        try (InputStream inputStream = file.getInputStream()) {

            // 使用EasyExcel读取原始文件数据
            EasyExcel.read(inputStream, new AnalysisEventListener<>() {
                @Override
                public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                    // 转换为小写并存储列头
                    List<String> headers = new ArrayList<>();
                    headMap.forEach((k, v) -> headers.add(ObjectUtils.isEmpty(v) ? "" : v.toLowerCase()));
                    headerData.add(headers);
                }

                @Override
                public void invoke(Object data1, AnalysisContext context) {
                    Map<Integer, String> stringData = (Map<Integer, String>) data1;
                    List<String> list = new ArrayList<>();
                    stringData.forEach((key, value) -> list.add(ObjectUtils.isEmpty(value) ? "" : value));
                    rowData.add(list);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 所有数据解析完成后调用此方法,这里不做什么
                }
            }).sheet().doRead();

            // 创建一个字节数组输出流来存储Excel内容
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            // 使用EasyExcel创建ExcelWriter
            try (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream).build()) {
                // 创建写入的sheet页
                WriteSheet writeSheet = EasyExcel.writerSheet().build();

                // 写入表头
                if (!headerData.isEmpty()) {
                    excelWriter.write(headerData, writeSheet);
                }

                // 写入数据
                if (!rowData.isEmpty()) {
                    excelWriter.write(rowData, writeSheet);
                }
            }

            // 将字节数组输出流转换为输入流
            InputStream newInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

            // 使用转换后的输入流创建一个新的MultipartFile
            return new MockMultipartFile(
                    "file",
                    file.getOriginalFilename(),
                    file.getContentType(),
                    newInputStream
            );
        }
    }
}

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

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

相关文章

【Linux取经路】文件系统——inode与软硬链接

文章目录 一、前言二、认识硬件——磁盘2.1 磁盘的存储构成2.2 磁盘的逻辑抽象 三、操作系统对磁盘的使用3.1 再来理解创建文件3.2 再来理解删除文件3.3 再来理解目录 四、硬链接五、软链接六、结语 一、前言 在之前的【Linux取经路】文件系统之被打开的文件——文件描述符的引…

【学习心得】响应数据加密的原理与逆向思路

一、什么是响应数据加密&#xff1f; 响应数据加密是常见的反爬手段的一种&#xff0c;它是指服务器返回的不是明文数据&#xff0c;而是加密后的数据。这种密文数据可以被JS解密进而渲染在浏览器中让人们看到。 它的原理和过程图如下&#xff1a; 二、响应数据加密的逆向思路 …

go并发模式之----使用时顺序模式

常见模式之二&#xff1a;使用时顺序模式 定义 顾名思义&#xff0c;起初goroutine不管是怎么个先后顺序&#xff0c;等到要使用的时候&#xff0c;需要按照一定的顺序来&#xff0c;也被称为未来使用模式 使用场景 每个goroutine函数都比较独立&#xff0c;不可通过参数循环…

Linux入门到入土

Linxu Linux 简介 Linux 内核最初只是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的。 Linux 是一套免费使用和自由传播的类 Unix 操作系统&#xff0c;是一个基于 POSIX&#xff08;可移植操作系统接口&#xff09…

常用的电阻、电容的种类和应用场合?

电阻的 a.按阻值特性:固定电阻、可调电阻、特种电阻(敏感电阻)&#xff0c;不能调节的,我们称之为固定电阻,而可以调节的,我们称之为可调电阻.常见的例如收音机音量调节的,主要应用于电压分配的,我们称之为电位器. b.按制造材料:碳膜电阻、金属膜电阻、线绕电阻&#xff0c;捷…

ElasticSearch开篇

1.ElasticSearch简介 1.1 ElasticSearch&#xff08;简称ES&#xff09; Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。能够达到实时搜索&#xff0c;稳定&#xff0c;可靠&#xff0c;快速&#xff0c;安装使用方便。 1.2 ElasticSearch与Lucene的关…

从0开始回顾Mysql --- MySQL初体验

大白话从0开始回顾MySQL&#xff0c;去除了一些繁琐的操作的演示以及内容&#xff0c;如MySQL安装等&#xff0c;本篇文章适合复习MySQL语法&#xff0c;学习MySQL语句&#xff0c;对MySQL不太熟练的同学&#xff0c;希望对大家有一些帮助。 MySQL初体验 首先&#xff0c;我将…

Linux内核MMC框架

1.mmc的概念 1.MMC MultiMedia Card&#xff0c;多媒体存储卡&#xff0c; 但后续泛指一个接口协定&#xff08;一种卡式&#xff09;&#xff0c;能符合这接口的内存器都可称作mmc储存体,工作电压&#xff1a;高电压为2.7&#xff5e;3.6 V&#xff0c;低电压为1.65&#xf…

Python——桌面摄像头软件(附源码+打包)

目录 一、前言 二、桌面摄像头软件 2.1、下载项目 2.2、功能介绍 三、打包工具&#xff08;nuitka&#xff09; 四、项目文件复制&#xff08;我全部合到一个文件里面了&#xff09; 五、结语 一、前言 看见b站的向军大叔用electron制作了一个桌面摄像头软件 但是&#x…

【应用多元统计分析】--多元数据的直观表示(R语言作图)

例1.2 为了研究全国31个省、市、自治区2018年城镇居民生活消费的分布规律&#xff0c;根据调查资料做区域消费类型划分。 指标&#xff1a; 食品x1&#xff1a;人均食品支出(元/人) 衣着x2&#xff1a;人均衣着商品支出(元/人) 居住x3&#xff1a;人均居住支出(元/人) 生活x4…

ssh无法直接登入Linux超级用户root(23/3/3更新)

说明&#xff1a;不允许ssh用超级用户的身份登入是为了安全性&#xff0c;如果只是学习使用对安全性没啥要求可以按以下操作解除限制 以普通用户登录到服务器后&#xff0c;执行以下命令以编辑 SSH 服务器配置文件 /etc/ssh/sshd_config sudo nano /etc/ssh/sshd_config 此时会…

二极管原理及典型应用电路、三极管基本结构及类型状态

目录 二极管原理及典型应用电路 二极管的工作原理 二极管保护电路 二极管整流电路 二极管稳压电路 三极管基本结构及类型状态 三极管基本结构和类型 三极管的 3 种工作状态 二极管原理及典型应用电路 如下图&#xff0c;二极管长成这样。它们通常有一个黑色圆柱体&am…

【大厂AI课学习笔记NO.60】(13)模型泛化性的评价

我们学习了过拟合和欠拟合&#xff0c;具体见我的文章&#xff1a;https://giszz.blog.csdn.net/article/details/136440338 那么今天&#xff0c;我们来学习模型泛化性的评价。 泛化性的问题&#xff0c;我们也讨论过了&#xff0c;那么如何评价模型的泛化性呢&#xff1f; …

论文精读--GPT3

不像GPT2一样追求zero-shot&#xff0c;而换成了few-shot Abstract Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnos…

二十四、剖析 ArrayDeque

文章目录 剖析 ArrayDeque3.1 循环数组3.2 构造方法3.3 从尾部添加 addLast(E)3.4 从头部添加 addFirst(E)3.5 从头部和尾部删除3.6 查看长度 size()3.7 检查给定元素是否存在3.8 toArray3.9 ArrayDeque 特点分析 剖析 ArrayDeque 本文为书籍《Java编程的逻辑》1和《剑指Java&…

Unity UGUI之Slider基本了解

在Unity中&#xff0c;Slider&#xff08;滑动条&#xff09;是一种常用的用户界面控件之一&#xff0c;允许用户通过拖动滑块来选择一个数值。常常应用于调节数值&#xff08;如调节音量、亮度、游戏难度等&#xff09;、设置选项等。 以下是Slider的基本信息和用法: 1、创建…

Neoverse CSS N3:实现市场领先能效的最快途径

区分老的架构 从云到边缘&#xff0c;Arm Neoverse 提供无与伦比的性能、效率、设计灵活性和 TCO 优势&#xff0c;正在颠覆传统基础设施芯片。 我们看到云和超大规模服务运营商正在推动更高的计算密度。随着 128 核心 CPU 设计上市&#xff08;Microsoft Cobalt、阿里巴巴 Y…

工作微信统一管理(还带监管功能)

1.会话页面(可统一管理多个微信号、聚合聊天、手动搜索添加好友、通过验证请求、查看好友的朋友圈等) 2.聊天历史(可查看 所有聊天记录&#xff0c;包括手机.上撤回、删除的消息) 3.群发助手(可以一 -次群发多个好友和群&#xff0c;还可以选择定时发送&#xff0c;目前还在内测…

postman传参与返回值切换为左右显示的操作

目录 第一步 点击“Settings”&#xff0c;在下拉框选择“Settings” 第二步 在默认打开的General页面&#xff0c;参照下图改动两处 第一步 点击“Settings”&#xff0c;在下拉框选择“Settings” 第二步 在默认打开的General页面&#xff0c;参照下图改动两处 附上修改后…

Mysql深入学习 基础篇 Ss.02 详解四类SQL语句

我亲爱的对手&#xff0c;亦敌亦友&#xff0c;但我同样希望你能成功&#xff0c;与我一起&#xff0c;站在人生的山顶上 ——24.3.1 一、DDL 数据定义语言 1.DDL —— 数据库操作 查询 查询所有数据库 show databases; 查询当前数据库 select database(); 创建 create databa…