随着企业信息化程度的提高,数据管理和处理变得越来越重要。Excel 文件作为常用的数据存储和交换格式,其导入功能在许多业务场景中不可或缺。本文将介绍如何使用 Spring Boot 框架结合 EasyExcel 和 Apache POI 库,实现高效的数据导入和图片处理功能。通过这一方案,开发者可以轻松地将 Excel 文件中的数据导入系统,并处理其中的图片,从而提升数据处理的效率和准确性。
前言
项目中,要求批量导入 Excel 数据并读取其中图片,目前 EasyExcel 不支持读取图片,因此需要使用 Apache POI 进行导入。然而Apache POI 需要开发者手动管理行、列、单元格等对象,相对较为底层且繁琐。
作者随即想到了一种方法,既能够使用 EasyExcel 的简便导入方式,又能够识别图片并进行处理。
相关依赖
<!-- Apache POI --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.3</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.2.1</version> </dependency>
Java 代码展示
import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.IdUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.util.ListUtils; import com.bi.my.vo.ExcelVo; import lombok.extern.slf4j.Slf4j; import net.dreamlu.mica.core.result.R; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.*; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * 数据+图片导入 * * @author wss */ @Slf4j @RestController @RequestMapping("/easy") public class EasyExcelController { /** * 数据导入并识别图片 * * @param file file * @return R<Object> * @author wss */ @PostMapping("/import") public R<Object> dataImport(@RequestParam("file") MultipartFile file) { List<ExcelVo> excelVos = new ArrayList<>(); //数据处理 this.dataProcess(file, excelVos); //图像处理 this.imageProcess(file, excelVos); //返回结果,这里也可以处理excelVos数据,如往mysql存储 return R.success(excelVos); } /** * 图片处理 */ public void imageProcess(MultipartFile file, List<ExcelVo> excelVos) { try { XSSFWorkbook book = new XSSFWorkbook(file.getInputStream()); //方式1 获取sheet数量,采用下标方式遍历读取每个工作表数据 int sheetsNos = book.getNumberOfSheets(); for (int sheetNo = 0; sheetNo < sheetsNos; sheetNo++) { Sheet sheet = book.getSheetAt(sheetNo); //...省略,内容为方式2 } //方式2 获取sheet数量,直接遍历读取每个工作表数据 for (Sheet sheet : book) { XSSFSheet xssSheet = (XSSFSheet) sheet; //获取工作表中绘图包 XSSFDrawing drawing = xssSheet.getDrawingPatriarch(); if (drawing == null) { break; } //获取所有图像形状 List<XSSFShape> shapes = drawing.getShapes(); //遍历所有形状 for (XSSFShape shape : shapes) { //获取形状在工作表中的顶点位置信息(anchor锚点) XSSFClientAnchor anchor = (XSSFClientAnchor) shape.getAnchor(); //图片形状在工作表中的位置, 所在行列起点和终点位置 short c1 = anchor.getCol1(); int r1 = anchor.getRow1(); String key = r1 + "行," + c1 + "列"; if (shape instanceof XSSFPicture) { try { XSSFPicture pic = (XSSFPicture) shape; //形状获取对应的图片数据 XSSFPictureData picData = pic.getPictureData(); //保存图片到本地 byte[] data = picData.getData(); //TODO 这里上传文件至oss并生成链接,这里不做过多描述,有疑问请参照oss服务调用 String fileName = "https://oss.cn/" + DateUtil.today() + "/" + IdUtil.simpleUUID() + "/" + picData.suggestFileExtension(); //fileTemplate.putObject(properties.getBucketName(), fileName, new ByteArrayInputStream(data)); //TODO 放入excel集合,这里行数要减去1,获取图片是从表头开始(表头位置为0),获取excelVos是从数据开始(第一条数据位置为0)他们相差一个表头,所以要减去1才能对应 excelVos.get(r1 - 1).setPicture(fileName); } catch (Exception e) { log.error("asyncImportList XSSFClientAnchor key|{} error|{}", key, e.getMessage()); } } } } } catch (Exception e) { log.error("asyncImportList XSSFWorkbook error|{}", e.getMessage()); } } /** * 数据处理 */ public void dataProcess(MultipartFile file, List<ExcelVo> excelVos) { // 这里默认读取第一个sheet try { EasyExcel.read(file.getInputStream(), ExcelVo.class, new ReadListener() { /** * 单次缓存的数据量 */ public static final int BATCH_COUNT = 100; /** *临时存储 */ private List<ExcelVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); @Override public void invoke(Object object, AnalysisContext context) { ExcelVo data = (ExcelVo) object; cachedDataList.add(data); if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { saveData(); } /** * 加上存储数据库 */ private void saveData() { log.info("已获取数据|{}条", cachedDataList.size()); excelVos.addAll(cachedDataList); } }).sheet().doRead(); } catch (IOException e) { e.printStackTrace(); } } }
import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; /** * 导入VO * * @author wss */ @Data public class ExcelVo { @ExcelProperty("序号") private Integer ordinal; @ExcelProperty("标题") private String title; @ExcelProperty("图片") private String picture; }
Excel 表格准备
excel表头需和实体字段相对应
Postman 调用测试
打开图片链接发现与excel中图片一致,对应数据一致,读取图片成功!
结尾
到这里,EasyExcel 导入带图片已完成!读取图片速度较慢,可以通过异步或其它方式优化处理,根据自己需求修改即可,这里就不进行说明了。
补充
项目中本人是通过@RequestExcel注解直接获取的excel数据,file专用于图片读取,即方法中不用再进行数据处理,代码更加简化。
这篇文章主要是用来处理读取图片的,这里就不再详细说明该注解了,感兴趣的小伙伴可以查阅一下相关资料。
/** * 数据导入并识别图片 * * @param file file * @return R<Object> * @author wss */ @PostMapping("/import") public R<Object> dataImport(@RequestParam("file") MultipartFile file, @RequestExcel List<ExcelVo> excelVos) { //图像处理 this.imageProcess(file, excelVos); //返回结果,这里也可以处理excelVos数据,如往库里存储 return R.success(excelVos); }
总结
本文详细介绍了如何在 Spring Boot 项目中使用 EasyExcel 和 Apache POI 库实现 Excel 文件的导入和图片处理功能。通过EasyExcel库,我们可以高效地读取和处理 Excel 文件中的数据,而Apache POI则帮助我们提取和保存文件中的图片。整个过程通过一个简单的控制器接口实现,确保了系统的易用性和扩展性。此外,本文还提供了异常处理机制,确保在数据处理过程中系统的稳定性和可靠性。通过这些技术手段,开发者可以快速构建出高效、稳定的数据导入和图片处理系统,满足各种业务需求。
本文来源于#王疏蔬,由@蜜芽 整理发布。如若内容造成侵权/违法违规/事实不符,请联系本站客服处理!
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/2549.html