1、添加依赖:

  1. <!-- 现在已经更新到1.1.2-beta5 -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>easyexcel</artifactId>
  5. <version>1.1.1</version>
  6. </dependency>

导入:

2、添加监听:

  1. package com.aikucun.goods.biz.easyexcel;
  2.  
  3. import com.aikucun.goods.dao.model.vo.SkuModel;
  4. import com.aikucun.goods.dao.model.vo.SkuUploadFailModel;
  5. import com.aikucun.sc.common.utils.BeanUtils;
  6. import com.alibaba.excel.context.AnalysisContext;
  7. import com.alibaba.excel.event.AnalysisEventListener;
  8. import com.google.common.collect.Lists;
  9. import org.apache.commons.lang3.StringUtils;
  10.  
  11. import java.util.List;
  12.  
  13. public class SkuUploadListener extends AnalysisEventListener {
  14.  
  15. private List<SkuUploadFailModel> uploadFailList = Lists.newArrayList();
  16.  
  17. private List<SkuModel> skuModelList = Lists.newArrayList();
  18.  
  19. private int totalSize = 0;
  20.  
  21. /**
  22. * 每解析一行,执行一次该方法
  23. */
  24. @Override
  25. public void invoke(Object object, AnalysisContext context) {
  26. totalSize++;
  27. SkuModel skuModel = (SkuModel) object;
  28. if (!checkData(skuModel)) {
  29. return;
  30. }
  31. skuModelList.add(skuModel);
  32. }
  33.  
  34. @Override
  35. public void doAfterAllAnalysed(AnalysisContext context) {
  36.  
  37. }
  38.  
  39. private boolean checkData(SkuModel skuModel) {
  40.  
  41. // 失败原因
  42. String failMessage = "";
  43. // itemCode
  44. String itemCode = skuModel.getItemCode();
  45.  
  46. if (null == skuModel) {
  47. failMessage = "数据为空";
  48. }
  49. // 验证sku
  50. if (StringUtils.isEmpty(itemCode)) {
  51. failMessage = "itemCode为空!";
  52. } else {
  53. if (skuModelList.contains(itemCode)) {
  54. failMessage = failMessage + "itemCode重复!";
  55. }
  56. }
  57. //品牌名称
  58. if (StringUtils.isEmpty(skuModel.getBrandName())) {
  59. failMessage = failMessage + "品牌名称为空!";
  60. }
  61. //条码必填
  62. if (StringUtils.isEmpty(skuModel.getBarCode())) {
  63. failMessage = failMessage + "条码为空!";
  64. }
  65.  
  66. if (StringUtils.isNotEmpty(failMessage)) {
  67. SkuUploadFailModel failModel = new SkuUploadFailModel();
  68. //数量校验???
  69. BeanUtils.convert(skuModel, failModel);
  70. failModel.setFailMessage(failMessage);
  71.  
  72. uploadFailList.add(failModel);
  73. return false;
  74. }
  75. return true;
  76.  
  77. }
  78.  
  79. public List<SkuUploadFailModel> getUploadFailList(){
  80. return uploadFailList;
  81. }
  82.  
  83. public List<SkuModel> getSkuModelList(){
  84. return skuModelList;
  85. }
  86.  
  87. public int getTotalSize() {
  88. return totalSize;
  89. }
  90. }

3、导入商品controller:

  1. @PostMapping("/import-sku-list-async")
  2. @ApiOperation("批量导入商品(异步)")
  3. public Result importSkuListAsync(@RequestBody MultipartFile file) {
  4. return skuService.importSkuListAsync(file);
  5. }

4、ServiceImpl

  1. @Override
  2. public Result importSkuListAsync(MultipartFile file) {
  3.  
  4. //1.参数校验
  5. if (file == null || file.isEmpty()) {
  6. throw new GoodsException("导入文件为空");
  7. }
  8. // 判断文件格式
  9. String filename = file.getOriginalFilename();
  10. String suffixName = filename.substring(filename.indexOf("."));
  11. if (!".xlsx".equalsIgnoreCase(suffixName) && !".xls".equalsIgnoreCase(suffixName)) {
  12. throw new GoodsException("文件格式要求:.xlsx/.xls");
  13. }
  14. dealDataAsync(file, suffixName);
  15. return Result.success();
  16. }
  17.  
  18. /**
  19. * 异步处理excel数据校验、落库、上传文件服务器等
  20. *
  21. * @param file
  22. */
  23. @Async
  24. public void dealDataAsync(MultipartFile file, String suffixName) {
  25.  
  26. InputStream inputStream = null;
  27. try {
  28. inputStream = file.getInputStream();
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32. //1.注册任务
  33. String dataFlag = System.currentTimeMillis() + "";
  34. // 任务注册
  35. Long id = reg("{\"service\":\"goods-web\"}", getUserName(), dataFlag, getRealName(), DataFileTaskTypeEnum.IMPORT.getType());
  36. if (id == null) {
  37. log.error("【导入商品】 uploadSkuFile 数据版本号:" + dataFlag + ", 注册导入任务失败");
  38. return;
  39. }
  40. //2.excel数据校验
  41. SkuUploadListener listener = new SkuUploadListener();
  42. dealExcel(listener, suffixName, id, dataFlag, inputStream);
  43.  
  44. //3.把错误数据分装集合中,正确数据封装集合中
  45. // 验证失败的数据
  46. List<SkuUploadFailModel> uploadFailList = listener.getUploadFailList();
  47. // 验证通过的数据
  48. List<SkuModel> skuModeList = listener.getSkuModelList();
  49. // 总数量
  50. int totalSize = listener.getTotalSize();
  51. //4.把成功集合插入数据库,错误数据上传文件服务器
  52. try {
  53. for (SkuModel skuModel : skuModeList) {
  54. Sku sku = new Sku();
  55. BeanUtils.copyProperties(skuModel, sku);
  56. saveOrUpdateSku(sku);
  57. }
  58. }catch (Exception e){
  59. log.error("【导入商品】 数据版本号:{},保存采购单报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
  60. finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", totalSize, 0, "保存到数据库报错", dataFlag);
  61. return;
  62. }
  63. //5.完成任务(上传失败数据到文件服务器)
  64. // 导入状态
  65. int status = DataFileTaskStatusEnum.SUCCESS.getType();
  66. String fileUrl = "";
  67. // 导入失败的数据,生成异常文件
  68. if (!CollectionUtils.isEmpty(uploadFailList)) {
  69. if (CollectionUtils.isEmpty(skuModeList)) {
  70. status = DataFileTaskStatusEnum.FAIL.getType();
  71. } else {
  72. status = DataFileTaskStatusEnum.PART_SUCCESS.getType();
  73. }
  74. fileUrl = createErrFile(uploadFailList, dataFlag);
  75. }
  76. finish(id, status, fileUrl, totalSize, skuModeList.size(), "导入结束", dataFlag);
  77. }
  78.  
  79. private void dealExcel(SkuUploadListener listener, String suffixName, Long id, String dataFlag, InputStream file) {
  80. ExcelTypeEnum excelTypeEnum;
  81. if (ExcelTypeEnum.XLSX.getValue().equalsIgnoreCase(suffixName)) {
  82. excelTypeEnum = ExcelTypeEnum.XLSX;
  83. } else if (ExcelTypeEnum.XLS.getValue().equalsIgnoreCase(suffixName)) {
  84. excelTypeEnum = ExcelTypeEnum.XLS;
  85. } else {
  86. log.error("【导入采购单】 uploadPurchaseFile 数据版本号:" + dataFlag + ",上传文件格式不是 " + ExcelTypeEnum.XLSX.getValue() + "/" + ExcelTypeEnum.XLS.getValue());
  87. finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "文件格式不正确", dataFlag);
  88. return;
  89. }
  90. // 解析文件
  91. try {
  92. ExcelReader excelReader = new ExcelReader(file, excelTypeEnum, null, listener);
  93. excelReader.read(new Sheet(1, 1, SkuModel.class));
  94. } catch (Exception e) {
  95. log.error("【导入采购单】 uploadPurchaseFile 数据版本号:{},解析文件报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
  96. finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "解析文件报错", dataFlag);
  97. return;
  98. }
  99. }
  100.  
  101. /**
  102. * 导入商品,异常文件生成
  103. *
  104. * @param modelList
  105. * @param dataFlag
  106. */
  107. private String createErrFile(List<SkuUploadFailModel> modelList, String dataFlag) {
  108. // 生成文件类型
  109. ByteArrayOutputStream out = null;
  110. String fileUrl = "";
  111. try {
  112. out = new ByteArrayOutputStream();
  113. ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
  114. if (modelList.size() > FILE_SIZE) {
  115. List<List<SkuUploadFailModel>> splitList = Lists.partition(modelList, FILE_SIZE);
  116. for (int i = 0; i < splitList.size(); i++) {
  117. //写一个sheet,
  118. Sheet sheet = new Sheet(i + 1, 0, SkuUploadFailModel.class);
  119. writer.write(splitList.get(i), sheet);
  120. }
  121. } else {
  122. //写一个sheet,
  123. Sheet sheet = new Sheet(1, 0, SkuUploadFailModel.class);
  124. writer.write(modelList, sheet);
  125. }
  126. writer.finish();
  127. CloudStorageService oss = oSSFactory.build();
  128. String path = oss.getDefaultPath("/导入商品异常反馈.xlsx");
  129. fileUrl = oss.upload((out).toByteArray(), path);
  130. log.info("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",生成文件url:" + fileUrl);
  131. } catch (Exception e) {
  132. log.error("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
  133. } finally {
  134. try {
  135. if (out != null) {
  136. out.close();
  137. }
  138. } catch (Exception e) {
  139. e.printStackTrace();
  140. }
  141. }
  142. return fileUrl;
  143. }
  144.  
  145. private Long reg(String param, String userName, String dataFlag, String realName, Integer type) {
  146.  
  147. DataFileTaskDTO dataFileTaskDTO = new DataFileTaskDTO();
  148. dataFileTaskDTO.setParams(param);
  149. dataFileTaskDTO.setDataType(SystemModuleEnum.DOWNLOAD_GOODS.getType());
  150. dataFileTaskDTO.setType(type);
  151. dataFileTaskDTO.setRemark(SystemModuleEnum.DOWNLOAD_GOODS.getTypeName() + ",数据版本号:" + dataFlag);
  152. dataFileTaskDTO.setSource(SystemModuleEnum.DOWNLOAD_GOODS.getSystem());
  153. dataFileTaskDTO.setCreateUser(realName);
  154. dataFileTaskDTO.setCreateUserJobNumber(userName);
  155.  
  156. log.info("【导入商品】推送到磐石注册任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(dataFileTaskDTO));
  157. Result ret = remote.reg(dataFileTaskDTO);
  158. log.info("【导入商品】推送到磐石注册任务返回结果,ret:{}", JSONObject.toJSONString(ret));
  159. if (!CheckUtils.isNull(ret) && ret.isSuccess() && ret.getData() != null) {
  160. return Long.parseLong( ret.getData().toString());
  161. }
  162. return null;
  163. }
  164.  
  165. private Long finish(Long id, Integer taskStatus, String fileUrl, Integer total, Integer successTotal, String remark, String dataFlag) {
  166.  
  167. DataFileTaskDTO taskDTO = new DataFileTaskDTO();
  168. taskDTO.setId(id);
  169. taskDTO.setTaskStatus(taskStatus);
  170. taskDTO.setFileUrl(fileUrl);
  171. taskDTO.setTotal(total == null ? 0 : total);
  172. taskDTO.setSuccessTotal(successTotal == null ? 0 : successTotal);
  173. taskDTO.setRemark(remark + ",数据版本号:" + dataFlag);
  174.  
  175. log.info("【导入商品】推送到磐石完成任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(taskDTO));
  176. Result ret = remote.finsh(taskDTO);
  177. log.info("【导入商品】推送到磐石完成任务返回结果,ret:{}", JSONObject.toJSONString(ret));
  178. if (!CheckUtils.isNull(ret) && ret.isSuccess()) {
  179. return (Long) ret.getData();
  180. }
  181. return null;
  182. }
  183.  
  184. /**
  185. * 获取用户名
  186. *
  187. * @return
  188. */
  189. private String getUserName() {
  190. // 获取当前用户
  191. String userName = "";
  192. LoginUserVo loginUserVo = UserVoThreadLocal.get();
  193. if (Objects.nonNull(loginUserVo)) {
  194. userName = loginUserVo.getUserName();
  195. }
  196. return userName;
  197. }
  198.  
  199. /**
  200. * 获取真实姓名
  201. *
  202. * @return
  203. */
  204. private String getRealName() {
  205. // 获取当前用户
  206. String realName = "";
  207. LoginUserVo loginUserVo = UserVoThreadLocal.get();
  208. if (Objects.nonNull(loginUserVo)) {
  209. realName = loginUserVo.getRealName();
  210. }
  211. return realName;
  212. }

导出:

1、导出controller

  1. /**
  2. * 导出维护记录
  3. * @param vo
  4. */
  5. @PostMapping("/download")
  6. @ApiOperation(value = "采购单下载")
  7. public Result<String> exportRecord(@RequestBody PurchaseOrderHeadVO vo) {
  8. purchaseManageService.exportRecord(vo);
  9. return Result.success("导出成功");
  10. }

2、serviceImpl

  1. @Async
  2. public void createRecordFile(PurchaseOrderHeadVO vo, String currentUserName, String realName,Long id,String dataFlag) {
  3. log.info("【导出采购单】 createRecordFile 开始,参数:{},用户:{},开始时间:{} ,数据版本号:{}", JSON.toJSONString(vo), currentUserName, System.currentTimeMillis(), dataFlag);
  4. // 任务注册
  5. if (id == null) {
  6. return;
  7. }
  8. // 生成文件类型
  9. ByteArrayOutputStream out = null;
  10. Map<String, Object> map = getStringObjectMap(vo);
  11. // 根据条件查询
  12. List<PurchaseOrderModel> list = purchaseOrderExtendMapper.listForEceport(map);
  13. if (CollectionUtils.isEmpty(list)) {
  14. log.info("【导出采购单】 createRecordFile 未查询到需要导出的数据,数据版本号:" + dataFlag);
  15. finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "查询数据为空", dataFlag);
  16. return;
  17. }
  18. try {
  19. // 批量生成文件,每个文件数据,最多 6万
  20. List<PurchaseDownloadModel> modelList = new ArrayList<>();
  21. for (PurchaseOrderModel entity : list) {
  22. PurchaseDownloadModel model = new PurchaseDownloadModel();
  23. BeanUtils.copyProperties(entity, model);
  24. // 采购模型
  25. model.setPurchaseMode(PurchaseModeDictEnum.getNameByCode(model.getPurchaseMode()));
  26. // 采购类型
  27. model.setPurchaseType(PurchaseTypeDictEnum.getNameByCode(model.getPurchaseType()));
  28. // 采购状态
  29. model.setStatus(PurchaseStatusEnum.getNameByCode(model.getStatus()));
  30. // 业务线
  31. model.setBusinessLine(PurchaseBusinessDictEnum.getNameByCode(model.getBusinessLine()));
  32. modelList.add(model);
  33. }
  34. out = new ByteArrayOutputStream();
  35. ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
  36. if (modelList.size() > FILE_SIZE) {
  37. List<List<PurchaseDownloadModel>> splitList = Lists.partition(modelList, FILE_SIZE);
  38. for (int i = 0; i < splitList.size(); i++) {
  39. //写一个sheet,
  40. Sheet sheet = new Sheet(i + 1, 0, PurchaseDownloadModel.class);
  41. writer.write(splitList.get(i), sheet);
  42. }
  43. } else {
  44. //写一个sheet,
  45. Sheet sheet = new Sheet(1, 0, PurchaseDownloadModel.class);
  46. writer.write(modelList, sheet);
  47. }
  48. writer.finish();
  49. CloudStorageService oss = oSSFactory.build();
  50. String path = oss.getDefaultPath("/采购单导出.xlsx");
  51. String url = oss.upload((out).toByteArray(), path);
  52. finish(id, DataFileTaskStatusEnum.SUCCESS.getType(), url, list.size(), list.size(), "导出成功", dataFlag);
  53. log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",生成文件url:" + url);
  54. } catch (Exception e) {
  55. log.error("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
  56. // 发生异常,删除文件
  57. finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", list.size(), 0, "导出报错,数版本号:" + dataFlag, dataFlag);
  58. } finally {
  59. try {
  60. if (out != null) {
  61. out.close();
  62. }
  63. } catch (Exception e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",结束,时间:" + System.currentTimeMillis());
  68. }

另外建议参考:https://github.com/HowieYuan/easyexcel-encapsulation

easyExcel用于导入导出的更多相关文章

  1. 使用Layui、Axios、Springboot(Java) 实现EasyExcel的导入导出(浏览器下载)

    实现EasyExcel的导入导出(浏览器下载) 实现三个按钮的功能,但是却花费了一天的时间包括总结. 使用到的技术:springboot layui axios EasyExcel mybatis-p ...

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

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

  3. PL/SQLDeveloper导入导出Oracle数据库方法

    前一篇博客介绍了Navicat工具备份Oracle的方法,这篇博客介绍一下使用PL/SQL Developer工具导入导出Oracle数据库的方法. PL/SQL Developer是Oracle数据 ...

  4. 分享一次Oracle数据导入导出经历

    最近工作上有一个任务要修改一个比较老的项目,分公司这边没有这个项目数据库相关的备份,所以需要从正式环境上面导出数据库备份出来在本地进行部署安装,之前在其它项目的时候也弄过这个数据库的部署和安装,也写了 ...

  5. PL/SQL Developer导入导出Oracle数据库方法

    前一篇博客介绍了Navicat工具备份Oracle的方法.这篇博客介绍一下使用PL/SQL Developer工具导入导出Oracle数据库的方法. PL/SQL Developer是Oracle数据 ...

  6. java使用户EasyExcel导入导出excel

    使用alibab的EasyExce完成导入导出excel 一.准备工作 1.导包 <!-- poi 相关--> <dependency> <groupId>org. ...

  7. SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能

      批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...

  8. .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)

    .Net MVC  导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构)   public cl ...

  9. Sqoop -- 用于Hadoop与关系数据库间数据导入导出工作的工具

    Sqoop是一款开源的工具,主要用于在Hadoop相关存储(HDFS.Hive.HBase)与传统关系数据库(MySql.Oracle等)间进行数据传递工作.Sqoop最早是作为Hadoop的一个第三 ...

随机推荐

  1. gogs 实现webhook钩子(php接口形式)

    1.概要流程 2.准备工作 gogs服务器 linux网站服务器(宝塔) 本地客户端 3.编写钩子访问的接口 在public下新建githook.php文件,代码如下: <?php $cmd = ...

  2. qemu通过控制台向虚拟机输入组合键

    ctrl+alt+2 开启控制台 ctrl+alt+1 关闭控制台 在控制台中输入 sendkey ctrl-alt-delete 发送指令

  3. centos7搭建maven私服

    Linux:CentOS7安装maven私服Nexus https://blog.csdn.net/plei_yue/article/details/78616267 搭建nexus3版的maven私 ...

  4. openresty开发系列27--openresty中封装redis操作

    openresty开发系列27--openresty中封装redis操作 在关于web+lua+openresty开发中,项目中会大量操作redis, 重复创建连接-->数据操作-->关闭 ...

  5. C++类成员存储大小

    1.对象分布图 2.解析 每个类的大小只有其成员变量大小,其中包括:类成员属性,虚函数指针: 而其他没有如:静态变量[静态区],普通函数.静态函数[代码区] 3.总结 类对象的sizeof只包含成员变 ...

  6. 基于Broadcast 状态的Flink Etl Demo

    接上文: [翻译]The Broadcast State Pattern(广播状态) 最近尝试了一下Flink 的 Broadcase 功能,在Etl,流表关联场景非常适用:一个流数据量大,一个流数据 ...

  7. delphi中我用定时器每隔一段时间执行操作

    delphi中,我用定时器每隔一段时间执行数据库插入及更新工作!adoquery.close;adoquery.sql.cleare;adoquery.connection:=con1;adoquer ...

  8. 一份 Tomcat 和 JVM 的性能调优经验总结!拿走不谢

    Tomcat性能调优 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创建 ...

  9. CompletableFuture Quasar 等并发编程

    CompletableFuture基本用法 https://www.cnblogs.com/cjsblog/p/9267163.html Quasar https://blog.csdn.net/ma ...

  10. docker 之网络配置

    Docker 网络实现 首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包:此外,如果不同子网之间要进行通信,需要路由机制. Docker 中的网络接口默认都是虚拟的接口 ...