目录

1、依赖引入和poi版本对应关系

2、web下载

2.1、实体对象注解方式

2.1.1、实体对象

2.1.2、接口代码

2.2、非实体对象注解方式

3、web上传

3.1、实体对象方式

3.1.1、实体对象对代码

3.1.2、接口代码

3.1.3、监听器

3.2、非实体对象方式

3.2.1、接口代码

3.2.2、监听器代码

3.3、根据路径读取


官方文档链接:EasyExcel · 语雀

1、依赖引入和poi版本对应关系

easyExcel版本与poi版本对应关系,这个是官方文档提供的说明

版本

poi依赖版本 (支持范围)

jdk版本支持范围

备注

3.1.0+

4.1.2 (4.1.2 - 5.2.2)

jkd8 - jdk17

推荐使用,会更新的版本

3.0.0-beta1 - 3.0.5

4.1.2 (4.1.2 - 5.2.2)

jkd8 - jdk11

不推荐项目新引入此版本,除非超级严重bug,否则不再更新

2.0.0-beta1-2.2.11

3.17 (3.17 - 4.1.2)

jdk6 - jdk11

不推荐项目新引入此版本,除非是jdk6否则不推荐使用,除非超级严重bug,否则不再更新

1+版本

3.17 (3.17 - 4.1.2)

jdk6 - jdk11

不推荐项目新引入此版本,超级严重bug,也不再更新

依赖引入

注意: 3+版本的的easyexcel,使用poi 5+版本时,需要手动排除:poi-ooxml-schemas

 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.0</version><exclusions><exclusion><artifactId>poi-ooxml-schemas</artifactId><groupId>org.apache.poi</groupId></exclusion></exclusions>
</dependency>

2、web下载

2.1、实体对象注解方式

2.1.1、实体对象

@Getter
@Setter
@EqualsAndHashCode
public class DownloadData {@ExcelProperty(value = "字符串标题", index = 1)private String string;@ExcelProperty(value = "日期标题", index = 2)private Date date;@ExcelProperty(value = "数字标题", index = 3)private Double doubleData;
}
@ExcelProperty注解value用于指定表头名字,index用于指定列下标

2.1.2、接口代码

    /*** 文件下载(失败了会返回一个有部分数据的Excel)* <p>* 1. 创建excel对应的实体对象 参照{@link DownloadData}* <p>* 2. 设置返回的 参数* <p>* 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大*/@GetMapping("download")public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());}/*** 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)** @since 2.1.1*/@GetMapping("downloadFailedUsingJson")public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmantry {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这里需要设置不关闭流EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板").doWrite(data());} catch (Exception e) {// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");Map<String, String> map = MapUtils.newHashMap();map.put("status", "failure");map.put("message", "下载文件失败" + e.getMessage());response.getWriter().println(JSON.toJSONString(map));}}

2.2、非实体对象注解方式

这种方式需要提供方法用于获取表头数据和内容数据

public void downloadDistributeTemplate(HttpServletResponse response) {// 表头数据封装List<List<String>> data = new ArrayList<>();List<String> rowOne = new ArrayList<>();rowOne.add("填写说明:只能分发一个产品下的设备,且最多 10000 个");List<String> rowTwo = new ArrayList<>();rowTwo.add("ProductKey");rowTwo.add("a1gMnLAmZ0F");List<String> rowThree = new ArrayList<>();rowThree.add("DeviceName");List<String> rowFour = new ArrayList<>();rowFour.add("sajdfhladJSDAJLFCjsdbca");data.add(rowOne);data.add(rowTwo);data.add(rowThree);data.add(rowFour);try {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("设备分发模板", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Access-Control-Expose-Headers", "content-disposition");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这里需要设置不关闭流EasyExcel.write(response.getOutputStream()).autoCloseStream(Boolean.FALSE).sheet("模板").registerWriteHandler(new OnceAbsoluteMergeStrategy(0, 0, 0, 5)).registerWriteHandler(new AbstractColumnWidthStyleStrategy() {@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {Sheet sheet = writeSheetHolder.getSheet();sheet.setColumnWidth(cell.getColumnIndex(), 3000);}}).doWrite(data);} catch (Exception e) {// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");throw ApiResult.resultCodeException(new AResultCode("0-90002", "下载文件失败"));}}

这里用到了两个策略

OnceAbsoluteMergeStrategy用于合并指定的单元格,如这里合并的是第一行第一个到第六个单元格

AbstractColumnWidthStyleStrategy用于设置单元格宽度

3、web上传

3.1、实体对象方式

3.1.1、实体对象对代码

@Getter
@Setter
@EqualsAndHashCode
public class UploadData {private String string;private Date date;private Double doubleData;
}

3.1.2、接口代码

    @Autowiredprivate UploadDAO uploadDAO;/*** 文件上传* <p>* 1. 创建excel对应的实体对象 参照{@link UploadData}* <p>* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link UploadDataListener}* <p>* 3. 直接读即可*/@PostMapping("upload")@ResponseBodypublic String upload(MultipartFile file) throws IOException {EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();return "success";}

注意:有个很重要的点 UploadDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring(如service和mapper)可以构造方法传进去

3.1.3、监听器

自定义一个监听器,去实现ReadListener接口即可,这里ReadListener传入的泛型是跟表头对象的实体对象

public class UploadDataListener implements ReadListener<UploadData> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;private List<UploadData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private UploadDAO uploadDAO;public UploadDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数uploadDAO = new UploadDAO();}/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param uploadDAO*/public UploadDataListener(UploadDAO uploadDAO) {this.uploadDAO = uploadDAO;}/*** 这个每一条数据解析都会来调用** @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*/@Overridepublic void invoke(UploadData data, AnalysisContext context) {log.info("解析到一条数据:{}", JSON.toJSONString(data));cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", cachedDataList.size());uploadDAO.save(cachedDataList);log.info("存储数据库成功!");}
}

3.2、非实体对象方式

这里跟实体对象方式差不多,只是在读取的时候read()方法不传入实体对象class,监听器的泛型对象使用Map

3.2.1、接口代码

@PostMapping("upload")@ResponseBodypublic String upload(MultipartFile file) throws IOException {EasyExcel.read(file.getInputStream(),  new DeviceDistributeListener()).sheet().doRead();return "success";}

3.2.2、监听器代码

public class DeviceDistributeListener implements ReadListener<Map<Integer, String>> {private List<String> deviceNameList;private String productKey;/*** 添加deviceName标识* */private boolean flag = false;@Overridepublic void invoke(Map<Integer, String> row, AnalysisContext analysisContext) {// row是行数据对象String data = row.get(0);if ("ProductKey".equals(data)) {productKey = row.get(1);return;}if ("DeviceName".equals(data)) {flag = true;deviceNameList = new ArrayList<>();return;}if (flag) {deviceNameList.add(data);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public List<String> getDeviceNameList() {return deviceNameList;}public String getProductKey() {return productKey;}
}

3.3、根据路径读取

部分成熟的业务或者公司会有自己的文件服务器,因此在进行web上传时往往会先把文件上传到文件服务器中,然后将文件的id保存下来,当需要解析的时候就是根据这个文件id获取到文件的url地址,此时获取该文件的输入流就需要使用new URL(path).openStream()这个方法

具体的service代码如下

try {EasyExcel.read(new URL(path).openStream(), new DeviceDistributeListener()).sheet().doRead();} catch (Exception e) {log.error("解析excel失败", e);throw ApiResult.resultCodeException(new AResultCode("0-90003", "解析excel失败"));}

其中path为根据文件id从文件服务器获取的文件url地址

EasyExcel web上传下载功能实现相关推荐

  1. JavaWeb实现文件上传下载功能实例解析

    转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...

  2. 文件的上传下载功能的实现(包括进度条)[telerik控件]

    文件的上传下载功能的实现(包括进度条) 1.准备工作 首先我们需要Telerik控件,数据库,上传文件文件夹. Telerik控件: RadUpload.RadProgressManager.RadP ...

  3. SpringBoot2.x集成mongoDB4.0实现音频文件的上传下载功能

    最近项目要用到文件上传下载功能,但是这些音频文件都很大,放到关系型数据库就不太好了(其实是太不好了),占内存不说还慢的要死,所以考虑使用分布式文件系统或者非关系型数据库来实现.由于分布式文件系统没有用 ...

  4. Spring Boot项目集成AWS SDK连接到AWS S3,实现上传下载功能

    本文主要描写在Spring Boot项目里集成AWS SDK连接到AWS S3,实现上传下载功能的具体代码和注意事项.如有不足和错误之处,欢迎指正. AWS S3相关介绍 AWS S3(官网): ht ...

  5. 教你如何实现c#文件上传下载功能

    简单介绍一下c#文件上传下载功能实现. NuGet 安装SqlSugar Model文件下新建 DbContext 类 public class DbContext {public DbContext ...

  6. ssm框架验证码图片加载不出_基于SSM框架的文件图片上传/下载功能实现

    前一段时间很多做毕业设计的同学问:如何写图片和文件的上传下载功能,今天正好有时间,所以就做了一个案例,详细的讲解这个功能. 框架结构: 对于很多做过开发的而言,上传功能肯定都用过,而且用到的场景很多, ...

  7. 项目_功能模块_基于Spring Boot的文件上传下载功能的设计与实现

    文章目录 基于Spring Boot的文件上传下载功能模块的设计与实现 1.前言 2.技术栈 3.关键源码 4.实现效果 4.1.登录 4.2.文件列表 4.3.上传文件测试 4.3.1.测试图片 4 ...

  8. java歌曲上传下载功能实现,Java上传下载功能的实现详解

    上传下载是很简单的功能,但是每次用的时候还是要查,这里整理一下 前台: 提交 主要注意: enctype="multipart/form-data" method="po ...

  9. C# web 上传下载文件

    C# web 上传下载文件文件类型不限制,只要客户单有相对应的文件 //上传 //上下文 System.Web.HttpFileCollection files = System.Web.HttpCo ...

最新文章

  1. Class对象和反射
  2. python调用kafka拉取数据失败_无法使用kafkapython从另一个容器向Kafka容器发出请求...
  3. 排序(选择,冒泡,直接插入,希尔排序)
  4. Windows 7技巧之Telnet组件消失之迷
  5. C语言高级编程:汇编分析i++和++i
  6. 3秒搞定!~~ 一亿数据获取前100个最大值
  7. 前端做后台管理系统有前途吗_关于后台管理系统前端项目的思考
  8. 弹性计算平台技术:云服务器“安全”“稳定”“弹性”的基石
  9. 价值98元的千神资源网模板
  10. 几种开源NOSQL数据库
  11. 无需多个模型也能实现知识整合?港中文MMLab提出“烘焙”算法,全面提升ImageNet性能...
  12. paip.接入支付接口功能流程总结
  13. C/C++正则表达式匹配数字范围/小数点后几位
  14. GameEntity(六)—— IChat
  15. 《Mars说光场》系列文章整理
  16. 游戏建模软件的ZBrush和Mudbox哪个好
  17. 遗传算法matlab_当结构设计遇到遗传算法应用ANSYS和MATLAB联合仿真优化设计探索(前传)...
  18. IOS逆向-动态调试
  19. 第3.1~3.3节《合成孔径雷达成像原理-皮亦鸣》
  20. 360儿童手表显示服务器错误,360儿童卫士刷机失败怎么办 刷机方法

热门文章

  1. android 检测软键盘,Android:检测软键盘打开
  2. 王者荣耀静态页面头部代码设计(2)
  3. matlab一元二次回归,MATLAB一元线性回归方程的计算及检验.doc
  4. Unity3D 矩阵运算
  5. chrome 浏览手机网站
  6. 拉依达准则的python代码
  7. 华为Mate30系列手机提前发布为哪般?
  8. 女孩子做项目管理的发展_我可以和孩子们一起做些有趣的技术项目吗?
  9. 使用FFmpeg设置视频文件的详细信息
  10. BUUCTF_Crypto_[MRCTF2020]天干地支+甲子