前言

在我们日常的开发过程中经常会使用Excel文件的形式来批量地上传下载系统数据,我们最常用的工具是Apache poi,但是如果数据到底上百万时,将会造成内存溢出的问题,那么我们怎么去实现百万数据批量导入导出。

正文

Easyexcel

Easyexcel 是阿里巴巴的开源项目,用来优化Excel文件处理过程:

poi消耗内存严重:Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但poi还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。

easyexcel针对内存做出了优化:重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出。

SpringBoot+ EasyExcel实现Excel文件的导入导出

导入依赖

org.projectlombok

lombok

1.18.2

true

com.alibaba

easyexcel

1.1.2-beat1

com.fasterxml.jackson.core

jackson-databind

com.fasterxml.jackson.core

jackson-annotations

com.fasterxml.jackson.core

jackson-annotations

为了防止Excel文件被破坏在pom.xml添加以下内容

org.apache.maven.plugins

maven-resources-plugin

xls

xlsx

application.propertis:配置文件

#temp files

project.tmp.files.path=/Users/mac/Desktop/image/tmp/files/

在SpringBoot启动类添加临时文件设置

@Value("${project.tmp.files.path}")

public String filesPath;

@Bean

MultipartConfigElement multipartConfigElement() {

MultipartConfigFactory factory = new MultipartConfigFactory();

//设置路径xxx

factory.setLocation(filesPath);

return factory.createMultipartConfig();

}

ExcelUtil:Excel工具类

@Slf4j

public class ExcelUtil {

private static Sheet initSheet;

static {

initSheet = new Sheet(1, 0);

initSheet.setSheetName("sheet");

//设置自适应宽度

initSheet.setAutoWidth(Boolean.TRUE);

}

public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {

try {

response.setCharacterEncoding("UTF-8");

response.setContentType("application/octet-stream;charset=utf-8");

response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

workbook.write(response.getOutputStream());

} catch (IOException e) {

// throw new NormalException(e.getMessage());

}

}

/**

* 读取少于1000行数据

*

* @param filePath 文件绝对路径

* @return

*/

public static List readLessThan1000Row(String filePath) {

return readLessThan1000RowBySheet(filePath, null);

}

/**

* 读小于1000行数据, 带样式

* filePath 文件绝对路径

* initSheet :

* sheetNo: sheet页码,默认为1

* headLineMun: 从第几行开始读取数据,默认为0, 表示从第一行开始读取

* clazz: 返回数据List 中Object的类名

*/

public static List readLessThan1000RowBySheet(String filePath, Sheet sheet) {

if (!StringUtils.hasText(filePath)) {

return null;

}

sheet = sheet != null ? sheet : initSheet;

InputStream fileStream = null;

try {

fileStream = new FileInputStream(filePath);

return EasyExcelFactory.read(fileStream, sheet);

} catch (FileNotFoundException e) {

log.info("找不到文件或文件路径错误, 文件:{}", filePath);

} finally {

try {

if (fileStream != null) {

fileStream.close();

}

} catch (IOException e) {

log.info("excel文件读取失败, 失败原因:{}", e);

}

}

return null;

}

/**

* 读大于1000行数据

*

* @param filePath 文件觉得路径

* @return

*/

public static List readMoreThan1000Row(String filePath) {

return readMoreThan1000RowBySheet(filePath, null);

}

/**

* 读大于1000行数据, 带样式

*

* @param filePath 文件觉得路径

* @return

*/

public static List readMoreThan1000RowBySheet(String filePath, Sheet sheet) {

if (!StringUtils.hasText(filePath)) {

return null;

}

sheet = sheet != null ? sheet : initSheet;

InputStream fileStream = null;

try {

fileStream = new FileInputStream(filePath);

ExcelListener excelListener = new ExcelListener();

EasyExcelFactory.readBySax(fileStream, sheet, excelListener);

return excelListener.getDatas();

} catch (FileNotFoundException e) {

log.error("找不到文件或文件路径错误, 文件:{}", filePath);

} finally {

try {

if (fileStream != null) {

fileStream.close();

}

} catch (IOException e) {

log.error("excel文件读取失败, 失败原因:{}", e);

}

}

return null;

}

/**

* 读大于1000行数据, 带样式

*

* @return

*/

public static List readMoreThan1000RowBySheetFromInputStream(InputStream inputStream, Sheet sheet) {

sheet = sheet != null ? sheet : initSheet;

InputStream fileStream = null;

ExcelListener excelListener = new ExcelListener();

EasyExcelFactory.readBySax(inputStream, sheet, excelListener);

return excelListener.getDatas();

}

/**

* 生成excle

*

* @param filePath 绝对路径

* @param data 数据源

* @param head 表头

*/

public static void writeBySimple(String filePath, List> data, List head) {

writeSimpleBySheet(filePath, data, head, null);

}

/**

* 生成excle

*

* @param filePath 路径

* @param data 数据源

* @param sheet excle页面样式

* @param head 表头

*/

public static void writeSimpleBySheet(String filePath, List> data, List head, Sheet sheet) {

sheet = (sheet != null) ? sheet : initSheet;

if (head != null) {

List> list = new ArrayList<>();

head.forEach(h -> list.add(Collections.singletonList(h)));

sheet.setHead(list);

}

OutputStream outputStream = null;

ExcelWriter writer = null;

try {

outputStream = new FileOutputStream(filePath);

writer = EasyExcelFactory.getWriter(outputStream);

writer.write1(data, sheet);

} catch (FileNotFoundException e) {

log.error("找不到文件或文件路径错误, 文件:{}", filePath);

} finally {

try {

if (writer != null) {

writer.finish();

}

if (outputStream != null) {

outputStream.close();

}

} catch (IOException e) {

log.error("excel文件导出失败, 失败原因:{}", e);

}

}

}

/**

* 生成excle

*

* @param filePath 路径

* @param data 数据源

*/

public static void writeWithTemplate(String filePath, List extends BaseRowModel> data) {

writeWithTemplateAndSheet(filePath, data, null);

}

/**

* 生成excle

*

* @param filePath 路径

* @param data 数据源

* @param sheet excle页面样式

*/

public static void writeWithTemplateAndSheet(String filePath, List extends BaseRowModel> data, Sheet sheet) {

if (CollectionUtils.isEmpty(data)) {

return;

}

sheet = (sheet != null) ? sheet : initSheet;

sheet.setClazz(data.get(0).getClass());

OutputStream outputStream = null;

ExcelWriter writer = null;

try {

outputStream = new FileOutputStream(filePath);

writer = EasyExcelFactory.getWriter(outputStream);

writer.write(data, sheet);

} catch (FileNotFoundException e) {

log.error("找不到文件或文件路径错误, 文件:{}", filePath);

} finally {

try {

if (writer != null) {

writer.finish();

}

if (outputStream != null) {

outputStream.close();

}

} catch (IOException e) {

log.error("excel文件导出失败, 失败原因:{}", e);

}

}

}

/**

* 生成多Sheet的excle

*

* @param filePath 路径

* @param multipleSheelPropetys

*/

public static void writeWithMultipleSheel(String filePath, List multipleSheelPropetys) {

if (CollectionUtils.isEmpty(multipleSheelPropetys)) {

return;

}

OutputStream outputStream = null;

ExcelWriter writer = null;

try {

outputStream = new FileOutputStream(filePath);

writer = EasyExcelFactory.getWriter(outputStream);

for (MultipleSheelPropety multipleSheelPropety : multipleSheelPropetys) {

Sheet sheet = multipleSheelPropety.getSheet() != null ? multipleSheelPropety.getSheet() : initSheet;

if (!CollectionUtils.isEmpty(multipleSheelPropety.getData())) {

sheet.setClazz(multipleSheelPropety.getData().get(0).getClass());

}

writer.write(multipleSheelPropety.getData(), sheet);

}

} catch (FileNotFoundException e) {

log.error("找不到文件或文件路径错误, 文件:{}", filePath);

} finally {

try {

if (writer != null) {

writer.finish();

}

if (outputStream != null) {

outputStream.close();

}

} catch (IOException e) {

log.error("excel文件导出失败, 失败原因:{}", e);

}

}

}

/*********************匿名内部类开始,可以提取出去******************************/

@Data

public static class MultipleSheelPropety {

private List extends BaseRowModel> data;

private Sheet sheet;

}

/**

* 解析监听器,

* 每解析一行会回调invoke()方法。

* 整个excel解析结束会执行doAfterAllAnalysed()方法

*

* @author: chenmingjian

* @date: 19-4-3 14:11

*/

@Getter

@Setter

public static class ExcelListener extends AnalysisEventListener {

private List datas = new ArrayList<>();

/**

* 逐行解析

* object : 当前行的数据

*/

@Override

public void invoke(Object object, AnalysisContext context) {

//当前行

// context.getCurrentRowNum()

if (object != null) {

datas.add(object);

}

}

/**

* 解析完所有数据后会调用该方法

*/

@Override

public void doAfterAllAnalysed(AnalysisContext context) {

//解析结束销毁不用的资源

}

}

/************************匿名内部类结束,可以提取出去***************************/

}

CommonUtil:工具类

public class CommonUtil {

/**

* 生成32位编码,不含横线

*

* @return uuid串

*/

public static String getUUID() {

String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");

return uuid.toUpperCase();

}

/**

* 得到当前日期格式化后的字符串,格式:yyyy-MM-dd(年-月-日)

* @return 当前日期格式化后的字符串

*/

public static String getTodayStr(){

return new SimpleDateFormat("yyyy-MM-dd").format(new Date()) ;

}

/**

* 将对象转化成json

*

* @param t

* @return

* @throws JsonProcessingException

*/

public static String toJson(T t) throws JsonProcessingException {

return OBJECT_MAPPER.get().writeValueAsString(t);

}

}

UserPojoRes:实体类

@Setter

@Getter

@ToString

public class UserPojoRes extends BaseRowModel implements Serializable {

private static final long serialVersionUID = -2145503717390503506L;

/**

* 主键

*/

@ExcelProperty(value = "ID", index = 0)

private String id;

/**

* 姓名

*/

@ExcelProperty(value = "用户名", index = 1)

private String name;

public UserPojoRes(String id, String name) {

this.id = id;

this.name = name;

}

public UserPojoRes(){

}

}

验证

模板下载

这里将模板文件放在resources中

@GetMapping("/exportExcelTempalte")

@ApiOperation(value = "下载导入模板")

public void exportExcelTempalte(HttpServletResponse response) throws Exception {

//Resource目录中的文件

String filePath = "/excels/导入模板.xlsx";

ClassPathResource classPathResource = new ClassPathResource(filePath);

Workbook workbook=WorkbookFactory.create(classPathResource.getInputStream());

ExcelUtil.downLoadExcel("导入模板.xlsx", response, workbook);

}

Excel文件导入

@PostMapping("/importExcel")

@ApiOperation(value = "Excel文件导入")

public Response importExcel(HttpServletRequest request, MultipartFile file, HttpServletResponse response) throws Exception {

List objects = ExcelUtil.readMoreThan1000RowBySheetFromInputStream(file.getInputStream(),null);

List list = new ArrayList<>();

for (Object o : objects) {

UserPojoRes userPojoRes = new UserPojoRes();

List stringList = (List) o;

userPojoRes.setId(stringList.get(0) != null ? stringList.get(0).toString() : "");

userPojoRes.setName(stringList.get(1) != null ? stringList.get(0).toString() : "");

list.add(userPojoRes);

}

String json = CommonUtil.toJson(list);

return new Response(json);

}

Excel文件导出

@Value("${project.tmp.files.path}")

public String filesPath;

@GetMapping("/exportExcel")

@ApiOperation(value = "Excel文件导出")

public void exportExcel(HttpServletResponse response) throws Exception {

//创建临时文件

String path = filesPath + CommonUtil.getUUID() + ".xlsx";

List list = new ArrayList<>();

UserPojoRes userPojoRes = new UserPojoRes("009", "张三");

UserPojoRes userPojoRes1 = new UserPojoRes("009", "李四");

list.add(userPojoRes);

list.add(userPojoRes1);

ExcelUtil.writeWithTemplate(path, list);

// 根据excel创建对象

Workbook workbook = WorkbookFactory.create(new FileInputStream(path));

String fileName = "用户模块" + CommonUtil.getTodayStr() + ".xlsx";

ExcelUtil.downLoadExcel(fileName, response, workbook);

}

到此这篇关于SpringBoot中EasyExcel实现Excel文件的导入导出的文章就介绍到这了,更多相关Java Excel文件导入导出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

easyexcel导入时读不到数据_SpringBoot中EasyExcel实现Excel文件的导入导出相关推荐

  1. easyexcel导入时读不到数据_java编程中通过easypoi导入excel文件并验证导入数据

    引言 现如今越来越多的web网站或者内部管理web系统都有自己的数据分析中心.其数据中心的数据有些来源于人工单独操作,某些来自人工搜集大量的信息后通过excel文件批量导入进系统.本博客将讲解在jav ...

  2. easyexcel导入时读不到数据_EasyExcel简单使用--导入excel数据

    读Excel 1.依赖包 com.alibaba easyexcel 2.0.5 2.代码import java.io.File; import com.alibaba.excel.EasyExcel ...

  3. easyexcel导入时读不到数据_easyexcel读取任意表格以及使用中的坑

    关于easyexcel通过模板读取表格的,网上已经有好多了,而且源码里也有详细的demo,这里就不在多说.这里记录一下我的使用. 一: 目前有个接口是上传Excel并且返回第一行,之前用的是POI,但 ...

  4. easyexcel导入时读不到数据_EasyExcel快速读写Excel数据

    Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有 ...

  5. 微信小程序 -- 数据库数据excel文件批量导入

    一.excel文件批量导入数据到数据库 1.创建node.js函数upload,点击upload右键外部终端中安装类库 npm install node-xlsx 2.云函数代码 const clou ...

  6. 前端实现excel文件的导入导出

    前端实现excel文件的导入导出 导入文件 导出文件 导入文件 html: <el-dropdown v-waves @command="handleBatchCommand" ...

  7. 将Excel文件数据库导入SQL Server

    将Excel文件数据库导入SQL Server的三种方案//方案一: 通过OleDB方式获取Excel文件的数据,然后通过DataSet中转到SQL Server openFileDialog = n ...

  8. 使用PHPExcel实现Excel文件的导入和导出(模板导出)

    在之前有写过一篇文章讲述了使用PHP快速生成excel表格文件并下载,这种方式生成Excel文件,生成速度很快,但是有缺点是: 1.单纯的生成Excel文件,生成的文件没有样式,单元格属性(填充色,宽 ...

  9. excel 服务器怎么添加文件,本地的Excel文件怎么导入到远端服务器的临时表中

    本地的Excel文件如何导入到远端服务器的临时表中? 现在我有一个excel文件,我想把里面的数据导入到远端服务器中去,但是那边规定不能修改数据库的结构,只能用临时表,那么请问大家,我怎么才能把exc ...

最新文章

  1. mqtt+htttp+websocket
  2. 高温预警c语言,注意 | 高温预警来了!最高38°C!高温7连击!
  3. 关于SparkStreaming的checkpoint的弊端
  4. 排序算法 之四 分类、时间/空间复杂度、如何选择
  5. Introduction-to-React-JS
  6. Python画板画图之美
  7. 自然语言处理与中文分词的难点总结--学习笔记
  8. 数据结构 二叉搜索树BST的实现与应用
  9. 【干货】美团大脑系列之商品知识图谱的构建及应用.pdf(附下载链接)
  10. 字段 密码有效期_你知道Linux中用户们的密码藏在哪儿吗?
  11. python进程间通信总结_进程间通信方式总结(优缺点)
  12. TreeList(一)
  13. c语言半壁江山回调函数,回调函数运行时间太长影响了程序性能,怎么办
  14. python中https请求的封装_python接口自动化9-https请求(SSL)
  15. mysql根据身份证得到年龄_MySQL根据身份证获取省份 年龄 性别
  16. linetv_LINE TV台湾版
  17. 忘记Windows服务器密码怎么办
  18. 常见的虚拟化软件及其特点。
  19. 五一,我们来欣赏一篇宋词
  20. JVM-什么是GC?

热门文章

  1. 使用路由器中碰到的问题总结
  2. 怀孕期间可以让孩子变漂亮的办法
  3. ResizeObserver loop limit exceeded
  4. SolidWorks装配体中让弹簧随装配体运动的方法
  5. GT20L16S1Y GT30L32S4W 横置竖排 转换为 横置横排
  6. Vue框架-01-了解并使用Vue
  7. PDF文件转成图片保存
  8. 我是如何走上程序员这条道路的
  9. django学习笔记- oneday
  10. 关于windows7 家庭版 中的各种坑