easyExcel实现excel文件上传和下载

2023-11-08

一、easyExcel简介

  在工作中,经常需要把excel中的数据导入系统,亦或是把系统中符合筛选条件的数据通过excel的方式导出。
  Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后的存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出;03版excel的处理采用POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便。

  引入jar包。由于easyExcel中已经引入poi-ooxml、poi等jar。如果开发的老项目中也有poi-ooxml、poi的引入,注意jar包版本问题。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <!--目前最新的版本-->
    <version>1.1.2-beta5</version>
</dependency>

  学习easyExcel最好的方式,就是下载源码,参考项目中的测试用例。本篇教程为实践的总结,解决了实际开发中遇到的问题。两者结合学习事半功倍。
easyExcel GitHub链接


二、controller层解析excel文件

  easyExcel源码的测试用例中,提供了多种读取excel的方法。比如:

  1. 07版本excel读数据量少于1千行数据。
    excel中每行数据解析成Object,该Object包含excel中一整行的数据。
  2. 07版本excel读数据量少于1千行数据,自动转成 javamodel。
    excel中每行数据解析成java对象,excel每列对应java对象的一个成员变量。
  3. 07版本excel读数据量大于1千行。
  4. 07版本excel读数据量大于1千行数据自动转成javamodel。

  建议采用第4种方式,因为满足的场景更多,03版excel处于淘汰阶段,不予介绍;上述提到4种excel解析方法具体该如何使用,可以参考easyExcel源码中的测试用例。
  easyExcel源码的测试用例中,仅给出mavan项目resource路径下静态excel文件的解析的demo程序,实际项目中,文件都来自ajax发送的请求体。下面给出实际开发中controller层的代码。

@ResponseBody
@RequestMapping(value = "/importExcel", method = RequestMethod.POST,
        produces = "application/json;charset=utf-8")
public Result batchAddByExcel(
@RequestParam(value = "excel", required = false) MultipartFile excel,
@RequestParam(value = "name", required = false) String currentUser,
@RequestParam(value = "userId", required = false) Integer userId,
BatchAddPromotionVO request) {
    // 打印入参日志
    log.info("request = {},name = {}", request, currentUser);
    // 进行参数校验,检查入参的合理性
    Result result = checkParam(excel, request);
    if (!result.isSuccess()) {
        return result;
    }
    
    Map<Integer, List<Object>> sheetRowModelMap = null;
    try {
        // 解析excel文档。具体如何解析,省略。请参考easyExcel的源码测试用例
        sheetRowModelMap = parseExcelData(excel);
    } catch (Exception e) {
        log.error("parseExcelData error = ", e);
        return Result.wrapError(1, "解析excel失败" + e.getMessage());
    }
    // 遍历excel数据转化为业务需要的VO数据
    List<SavePromotionVO> list = parseExcelDataToVO(request, sheetRowModelMap);
    // 进行业务代码编写
    return Result.wrapSuccess(true);;
}

  注意点:在校验excel文件的合理性时,用下面的方式可能是有问题的。

private Result checkParam(MultipartFile excel, BatchAddPromotionVO request) {
        if (excel == null || request == null) {
            return Result.wrapError(1, "参数异常");
        }
        // excel文件的扩展名是可以是大写的 XLSX,所以这么判断不完整
        if (!excel.getOriginalFilename().contains(".xlsx")) {
            return Result.wrapError(1, "文件格式错误,请重新下载模板");
        }
        return Result.wrapSuccess(true);
    }

  上述代码中BatchAddPromotionVO,是一个复杂的java对象,定义如下:

package com.missfresh.pmp.admin.vo.productPromotion;

import com.alibaba.fastjson.JSONArray;
import com.missfresh.domain.Result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BatchAddPromotionVO {
    private String operateGroup;
    private Integer promoteLevel;
    private Integer businessType;
    /**
     * 位置信息,用于接收一个大json字符串
     */
    private String positionString;
    /**
     * 上面的 positionString接收到参数后,需要编写代码将其 转成 positionList
     */
    private List<PositionVO> positionList;
}

  这个controller方法既需要上传excel文件,又需要上传一堆业务参数。代码编写完成后,使用postman调用接口,是一个问题,该如何调接口?如下图所示:
在这里插入图片描述


三、controller层导出excel文件

  首先需要了解什么是 MIME TYPE?链接:https://www.cnblogs.com/jsean/articles/1610265.html
  easyExcel中的测试用例中也给出了多种写静态excel文件的方法,可以供开发者学习。在实际的业务中,需要把符合筛选条件的数据通过excel的方式导出、提供下载excel的功能。

@ResponseBody
@RequestMapping(value = "/exportSelectedPromotion.do", 
method = RequestMethod.POST, produces = "application/json;charset=utf-8")
public void exportPromotionByExcel07(@RequestBody PromotionListQueryVO queryVO, 
								HttpServletResponse response) {
    log.info("queryVO = {}", queryVO);
    try {
        // 查符合筛选条件的数据
        List<PromotionDTO> list = getPromotionDTOList(queryVO);
        
        // 把符合条件的数据,转化成写excel需要的Model实体
        List<PromotionWriteModel> modelList = converseListToWriteModel(list);

        String time = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        // 指定导出的excel文件的名字
        String fileName = "promotion_export_" + time;
        // 指定工作簿的名字
        String sheetName = "sheet1";

        // easyexcel工具类实现Excel文件导出(下文给出ExcelUtil的代码)
        ExcelUtil.writeExcel(response, modelList, fileName, sheetName, new PromotionWriteModel());

    } catch (Exception e) {
        e.printStackTrace();
        log.error("exportPromotionByExcel07 error:", e);
    }
}

ExcelUtil代码如下:

package com.missfresh.pmp.admin.util;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;

public class ExcelUtil {
    /**
     * 导出 Excel :一个 sheet,带表头.
     *
     * @param response  HttpServletResponse
     * @param list      数据 list,每个元素为一个 BaseRowModel
     * @param fileName  导出的文件名
     * @param sheetName 导入文件的 sheet 名
     * @param model     映射实体类,Excel 模型
     * @throws Exception 异常
     */
    public static void writeExcel(
        HttpServletResponse response, List<? extends BaseRowModel> list,
        String fileName, String sheetName, BaseRowModel model) throws Exception {
        ExcelWriter writer = 
        new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
        Sheet sheet = new Sheet(1, 0, model.getClass());
        sheet.setSheetName(sheetName);
        writer.write(list, sheet);
        writer.finish();
    }

    /**
     * 导出文件时为Writer生成OutputStream.
     *
     * @param fileName 文件名
     * @param response response
     * @return ""
     */
    private static OutputStream getOutputStream(String fileName, 
            HttpServletResponse response) throws Exception {
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e) {
            throw new Exception("导出excel表格失败!", e);
        }
    }
}

Postman调接口测试:
在这里插入图片描述

四、注意事项

  填入excel中的数据,按键盘del键删不干净,easyExcel在解析时依然可以读到del键删过的单元格,bean里每个元素都解析成了null,过滤掉这些bean就行。临时解决办法时,别操作del键。选中要删除的 行 – 右键 —删除,这样能删干净。如下图:
在这里插入图片描述


end,转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

easyExcel实现excel文件上传和下载 的相关文章

  • Mac M1安装Homebrew 简单实用

    1 首先创建安装目录 sudo mkdir p opt homebrew 2 将目录属主修改为当前用户 方便直接实用brew install sudo chown R whoami opt homebrew 3 进入 opt文件夹 cd o
  • vite插件介绍 - vite-plugin-meta-env

    vite插件介绍 vite plugin meta env a vite plugin define dynamic env variables in import meta env npm github 可以基于本仓库去开发自己的vite
  • 图像镜像翻转

    将图像左右镜像翻转 生成翻转后的图像 python3代码 import numpy as np import cv2 import matplotlib pyplot as plt 图片镜像翻转 def left2right img pat
  • 专业CPU信息检测工具:CPU-Z

    今天小编为大家测试了一款轻量级的CPU处理器的测试工具 可以查看CPU的详细信息 以供各位同学们学习 一 简单介绍 CPU Z是一款非常流行的CPU检测软件 被广大用户所熟知 它是目前最受欢迎的CPU检测软件之一 除了Intel和AMD自带
  • 代码走查——项目走向成功的锦囊之一

    说起代码走查 相信每个人都不陌生 但为什么要执行代码走查 什么时候来执行代码走查 如何有效执行代码走查 很多人的看法和见解都不一样 一般的看法 认为代码走查是一种非正式的代码评审技术 它通常在编码完成之后由代码的作者向一组同事来讲解他自己编
  • idea同一程序打开多个控制台

  • 怎么转发CSDN中的文章

    2018年09月24日 19 28 33 jackfjw 阅读数 900更多 分类专栏 Html 版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csd
  • 【Apifox Helper】自动生成接口文档,IDEA+Apifox懒人必备

    文章目录 前言 缘由 接口文档对接爽 整理起来真费脑 本文阅读时长 约10分钟 前置条件 1 IDEA开发工具 2 Apifox 不必要 主要目标 一秒生成接口文档 水图 IDEA中项目接结构图 生成到Apifox接口文档图 试用人群 1
  • Android Studio Unsupported Java

    问题 升级 Android Studio Flamingo 出现如下报错信息 Unsupported Java Your build is currently configured to use Java 17 0 2 and Gradle
  • 解决tqdm在jupyter中报错ImportError: IProgress not found. Please update jupyter and ipywidgets.

    解决方案 gt gt gt pip3 install ipywidgets
  • Markdown基本语法

    Markdown基本语法 一 Markdown了解 二 基本语法 1 各级标题的写法 2 段落 3 字体样式 4 分隔线 5 下划线 6 脚注 7 列表 8 代码块 9 引用 10 图片插入 11 链接 12 表格 三 高级技巧 1 HTM
  • Java:List<Map>指定Key去重,差集(针对集合里面只有Map非实体对象)

    ListMap去重 差集 针对集合里面只有Map非实体对象 问题 由于业务需求 接口的入参出参都是List格式 对于有些查出来的数据 为了防止重复的数据 需要对集合去重 以下分享一种去重的方法 该方法可根据指定字段对List
  • idea 生成类图

    选中类 ctrl alt u或者ctrl alt shift u 生成类图
  • 组合测试方法PK正交分析方法

    测试过程中 我们经常遇到需要覆盖多个变化参数的测试场景 如我们测试BS配置控制客户端组织资源远程配置一个设备时 进行一个设备通道视频参数设置的各种组合测试 如下图 多数情况下 类似于这种多组合测试时 老员工则是依靠经验去进行有针对性的测试
  • iOS系统网络抓包方法

    原文地址 http www cnblogs com ydhliphonedev archive 2011 10 27 2226935 html 在进行iOS开发过程中 经常会遇到各种各样的网络访问问题 以前苦于没有抓包工具 很多网络问题解决
  • IAR 编译异常记录

    问题一 问题描述 WARNING the connected j link is defective proper operation cannot be guaranteed 连接的J Link不良 无法保证正确操作 问题原因 驱动版本与
  • 为 SQL Server 站点数据库服务器配置 SPN

    如何为 SQL Server 站点数据库服务器配置 SPN 主题上次更新时间 2008 年 1 月 使用 SQL Server 计算机的本地系统帐户运行 SQL Server 服务不是 SQL Server 最佳方案 为了最安全地运行 SQ
  • APT攻击流程图画法参考

    APT攻击流程图画法参考 画图网站 多组件多阶段 多文件多次网络连接行为 ATTCK Kill Chain 画图网站 我用免费的ProcessOn 图标比较多也好看 个人免费文件是9个 如果不够用只能删了 花钱是不可能花钱的 删之前可以保存
  • 不瞒各位,不安装软件也能操作Xmind文档

    大家好 我是小悟 作为搞技术的一个人群 时不时就要接收产品经理发过来的思维脑图 而此类文档往往是以Xmind编写的 如果你的电脑里面没有安装Xmind的话 不好意思 是打不开这类后缀结尾的文档 打不开的话就看不到 无法洞察产品经理的意思 无
  • 基于vue-cli快速发布vue npm 包

    一 编写组件 1 初始化项目并运行 vue create vue digital count npm run serve 2 组件封装 新建package文件夹 因为我们可能会封装多个组件 所以在src下面新建一个 package 文件夹用

随机推荐