实现EasyExcel的导入导出(浏览器下载)

实现三个按钮的功能,但是却花费了一天的时间包括总结。

使用到的技术:springboot layui axios EasyExcel mybatis-plus

上传模板

不需要用到后端的交互,只需要前段<a>即可

<a href="../static/excel/用户信息上传模板.xlsx" style="color:white">上传模版</a>

参考链接:

Excel如何对某一列设置下拉选择项 https://jingyan.baidu.com/article/f7ff0bfccae0e62e26bb1380.html

下载上传模板 https://www.bilibili.com/video/BV1dQ4y1A75e?from=search&seid=16041556233389040505

导入数据

使用到EasyExcel的读Excel

后端

引入pom.xml 依赖

		<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.7</version>
</dependency>

对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDataExcel { @ExcelProperty("用户名")
private String userName;
@ExcelProperty("密码")
private String password;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("联系方式")
private String phone;
@ExcelProperty("用户类型")
private String typeStr;//取得的名字和User不一样,否则BeanUtils.copyProperties报错
@ExcelProperty("备注")
private String remark;
}

监听器

public class UserDataExcelListener extends AnalysisEventListener<UserDataExcel> {
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<User> list = new ArrayList<>();
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/ private UserService userService; public UserDataExcelListener() { }
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*/
public UserDataExcelListener(UserService userService ) {
this.userService = userService;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data
* one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
//一行行读取
@Override
public void invoke(UserDataExcel data, AnalysisContext context) {
if(data==null){
throw new DormitoryException(ResultCode.ERROR,"文件数据为空");
}
//进行数据的转换 第一个参数复制到第二个参数中
User user = new User();
BeanUtils.copyProperties(data,user);
if(!StringUtils.isEmpty(data.getTypeStr())){
switch (data.getTypeStr()){
case "管理员":
user.setType(0);
break;
case "宿管员":
user.setType(1);
break;
case "学生":
user.setType(2);
break;
}
}
System.out.println("将excel的data复制到user,user:"+user);
list.add(user);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
}
/**
* 加上存储数据库 在监听器中直接添加
*/
private void saveData() { userService.saveBatch(list); }
}

UserController 控制层

@PostMapping("addUsers")
public Result addUsers(@RequestParam("uploadFile") MultipartFile file) throws IOException {
if(file==null){
System.out.println("文件为空");
}
boolean save = userService.addUsers(file);
return save ? Result.ok().mesaage("新增用户成功"):Result.error().mesaage("新增用户失败");
}

UserServiceImpl 业务实现层

需要注意的点,因为监听器没有Spring进行管理,所以这边的处理方式是将UserService 传入进去

@Override
public boolean addUsers(MultipartFile file) {
try{
InputStream in = file.getInputStream();
EasyExcel.read(in, UserDataExcel.class, new UserDataExcelListener(this)).sheet().doRead();
}catch (Exception e){
e.printStackTrace();
}
return true;
}

经过上面的步骤后,我们就可以先在apipost中测试接口

apipost测试MultipartFile 下面有几个注意点需要注意

前端

<button class="layui-btn  layui-btn-sm " lay-event="importData" style="background: #2ecc71" > 导入数据 </button>

使用到了layui的上传组件,由于使用到axios,也简单地修改了一下upload的源码中的axios

upload.render({
elem:'#importExcel',
url:'/user/addUsers',
size : '5000',//文件最大可允许上传的大小,单位 KB
accept:'file',//允许上传文件
exts:'xls|xlsx|xlsm|xlt|xltx|xltm',
field:'uploadFile',
headers: {token: store.getToken()},
done:function (result) {//执行上传请求后的回调。返回三个参数,分别为:res(服务端响应信息)、index(当前文件的索引)、upload(重新上传的方法,一般在文件上传失败后使用)
console.log(result);
if(result.code==0){
layer.msg("Excel导入数据成功",{ },function () {
table.reload("user-table-id");
})
}else{
layer.msg("Excel导入数据失败",function () { })
}
}
});

小插曲的Bug,写在下面这篇博客中。

layui在toolbar使用上传控件在reload后失效的问题解决

参考链接 :

java+layui实现Excel的导入导出 https://www.cnblogs.com/bbllw/p/10800161.html

EasyExcel 文档 https://www.yuque.com/easyexcel/doc/easyexcel

课程上传的例子 https://www.bilibili.com/video/BV1dQ4y1A75e?from=search&seid=16041556233389040505

layui的upload文档说明 https://www.layui.com/doc/modules/upload.html

导出全部

使用到EasyExcel的写Excel,这一点也是最难的一点,主要是卡在文件在浏览器中下载。

如果直接使用EasyExcel中简单写的例子,只能将xlsx文件下载到后端的项目文件中,不能在浏览器中下载。

后端

	@GetMapping("exportAll")
public void exportAll(HttpServletResponse response) throws IOException {
List<UserDataExcel> listExcel = new ArrayList<>();
List<User> list = userService.list();
for(int i = 0;i<list.size();i++){
UserDataExcel dataExcel = new UserDataExcel();
BeanUtils.copyProperties(list.get(i),dataExcel);//小技巧
if(list.get(i).getType()!=null){//处理数据库中存放int 不是String
switch (list.get(i).getType()){
case 0:
dataExcel.setTypeStr("管理员");
break;
case 1:
dataExcel.setTypeStr("宿管员");
break;
case 2:
dataExcel.setTypeStr("学生");
break;
}
}
listExcel.add(dataExcel);
}
//文件名需要这样写,不能在setHeader直接写中文名,否则下载的文件名字为空,只有后缀
String fileName = new String("用户信息.xlsx".getBytes(), StandardCharsets.ISO_8859_1);
response.setContentType("application/msexcel");
response.setCharacterEncoding("utf8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName );
EasyExcel.write(response.getOutputStream(), UserDataExcel.class)
.sheet("sheet")
.doWrite(listExcel);
// return Result.ok().mesaage("下载成功"); 不要写
}

如果加了return Result.ok().mesaage("下载成功");后端会报错,但是还是可以正常下载。

org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.dj.dormitory.commonutils.Result] with preset Content-Type 'application/msexcel;charset=utf8'

前端

<button class="layui-btn  layui-btn-sm " lay-event="exportData" style="background: #27ae60"> 导出全部 </button>

刚开始的时候,自己想直接使用windows.open('/接口地址'),但是因为项目中用到token,所以就放弃了这个方法。使用了下面的方法

layer.confirm('确定导出所有用户信息吗?', {
btn: ['确定', '取消']
}, function(index){
//window.open("http://localhost:8888/dormitory/user/exportAll");
axios({
method: 'get',
url:'/user/exportAll',
responseType: 'blob', // 重要, 限制返回的数据结构为blob格式,方便前端做转换
}).then(data=>{
const link = document.createElement('a')
const blob = new Blob([data], { type: 'application/vnd.ms-excel' })
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.setAttribute('download','用户信息.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
layer.close(index);
}, function(index){
//按钮【按钮二】的回调
});

参考链接:

学到了 web中的代码具体应该怎么写

EasyExcel web中的写 https://www.yuque.com/easyexcel/doc/write#afb7324a

了解到window.open("/download");,可以在浏览器中实现成功下载了

EasyExcel实现下载Excel(解决无法从浏览器下载问题)https://blog.csdn.net/ruanbigshuai/article/details/108554896

了解到window.open("/download");最简单,但是不可以携带token

axios实现excel文件下载 https://blog.csdn.net/xuesheng1610748/article/details/83865679

成功帮助到自己的方法三,使用token并且在浏览器中实现成功下载了

Vue项目利用axios请求接口下载excel(附前后端代码) https://blog.csdn.net/asmallprogrammer/article/details/91440793

使用Layui、Axios、Springboot(Java) 实现EasyExcel的导入导出(浏览器下载)的更多相关文章

  1. 使用VUE+SpringBoot+EasyExcel 整合导入导出数据

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据 创建一个普通的maven项目即可 项目目录结构 1 前端 存放在resources/static 下 index.html &l ...

  2. java实现excel的导入导出(poi详解)[转]

    java实现excel的导入导出(poi详解) 博客分类: java技术 excel导出poijava  经过两天的研究,现在对excel导出有点心得了.我们使用的excel导出的jar包是poi这个 ...

  3. java实现文件批量导入导出实例(兼容xls,xlsx)

    1.介绍 java实现文件的导入导出数据库,目前在大部分系统中是比较常见的功能了,今天写个小demo来理解其原理,没接触过的同学也可以看看参考下. 目前我所接触过的导入导出技术主要有POI和iRepo ...

  4. Java实现大批量数据导入导出(100W以上) -(二)导出

    使用POI或JXLS导出大数据量(百万级)Excel报表常常面临两个问题: 1. 服务器内存溢出: 2. 一次从数据库查询出这么大数据,查询缓慢. 当然也可以分页查询出数据,分别生成多个Excel打包 ...

  5. Java实现大批量数据导入导出(100W以上) -(一)导入

    最近业务方有一个需求,需要一次导入超过100万数据到系统数据库.可能大家首先会想,这么大的数据,干嘛通过程序去实现导入,为什么不直接通过SQL导入到数据库. 大数据量报表导出请参考:Java实现大批量 ...

  6. java 中Excel的导入导出

    部分转发原作者https://www.cnblogs.com/qdhxhz/p/8137282.html雨点的名字  的内容 java代码中的导入导出 首先在d盘创建一个xlsx文件,然后再进行一系列 ...

  7. java的excel表格的导出与下载

    今天做一个java对excel表格的导出和下载的时候,从网络上搜寻了下载的模板,代码如下: 控制层: @RequestMapping(value = "excelOut_identifier ...

  8. Java实现大批量数据导入导出(100W以上) -(三)超过25列Excel导出

    前面一篇文章介绍大数据量导出实现: Java实现大批量数据导入导出(100W以上) -(二)导出 这篇文章在Excel列较少时,按以上实际验证能很快实现生成.但如果列较多时用StringTemplat ...

  9. JAVA对Excel的导入导出

    今天需要对比2个excel表的内容找出相同:由于要学的还很多上手很慢所以在这做个分享希望对初学的有帮助: 先是pom的配置: <dependency> <groupId>org ...

随机推荐

  1. php-fpm的慢执行日志

    通过慢执行日志,我们可以清晰地了解PHP脚本在哪里执行时间长,可以定位到行 下面介绍如何开启和查看慢执行日志 #vim /usr/local/php-fpm/etc/php-fpm.d/www.con ...

  2. C语言知识汇总,史上最全面总结,没有之一

    C语言基础 C语言学习路线 C语言入门笔记 初识C语言 简单的C程序示例 我们编写的C代码是怎样跑起来的? 简单示例,VS2019调试C语言程序 C语言基础-数据类型 深入理解变量,变量的声明,定义, ...

  3. python模块的打包和安装

    假设需要打包的模块文件名是mm.py,代码如下: a = 2 在mm.py文件的同目录下新建一个setup.py文件,代码如下: from distutils.core import setup se ...

  4. 【体系结构】Oracle进程架构

    Client Process的介绍 Client and Server Processes Client Process代表着客户端进程,每一个客户端进程关联着一个Server Process(服务器 ...

  5. POJ1979_Red and Black(JAVA语言)

    思路:bfs裸题. 对这种迷宫问题的bfs,我们把坐标点用一个class来存储,并放入队列进行求解. //一直接收不了输入,找了一个多小时的问题,居然是行和列搞反了ORZ Red and Black ...

  6. golang 性能优化分析:benchmark 结合 pprof

    前面 2 篇 golang 性能优化分析系列文章: golang 性能优化分析工具 pprof (上) golang 性能优化分析工具 pprof (下) 一.基准测试 benchmark 简介 在 ...

  7. 当初自学C++时的笔记记录

    编辑:刘风琛 最初编写日期:2020年4月11日下午 最新更新日期:2020年9月20日上午 标注: 从笔记开始截止到程序第四章"程序流程结构",使用Joplin编写,其余部分为T ...

  8. UnitTwoSummary

    目录 一.设计策略与程序分析 第一次作业 第二次作业 第三次作业 二.可扩展性检查与分析 三.bug 四.总结与反思 一.设计策略与程序分析 第一次作业 设计思路 输入,调度器,电梯分别设置成三个线程 ...

  9. Spring(四)Spring JdbcTemplate&声明式事务

    JdbcTemplate基本使用 01-JdbcTemplate基本使用-概述(了解) JdbcTemplate是spring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装.spr ...

  10. CentOS8搭建FTP服务器

    2021.2.20 更新 1 概述 文章核心: CentOS8使用vsftpd搭建FTP服务器 安装以及测试的详细过程 2 安装 2.1 安装vsftpd+ftp sudo yum install - ...