文章目录

  • 背景介绍
    • easyexcel 表头及数据
      • 表头
        • 简单
        • 合并
    • web项目导出方式
  • 实践出真知
    • 简单动态表头案例
    • 遇到的问题
      • 前端联调时excel无法打开
      • 下载文件接口有时返回文件流有时返回json的情况

导出数据是后端经典模块之一,从原有的poi到现在的easyexcel等等都在努力的帮助开发们缩小数据与excel之间的鸿沟。但是在简单的导出也会遇到一些有的没的问题,特地写个文章记录下~

背景介绍

一般导出流程图如下:

#mermaid-svg-XjAAJ7fe8d3cHM3C .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .label text{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .node rect,#mermaid-svg-XjAAJ7fe8d3cHM3C .node circle,#mermaid-svg-XjAAJ7fe8d3cHM3C .node ellipse,#mermaid-svg-XjAAJ7fe8d3cHM3C .node polygon,#mermaid-svg-XjAAJ7fe8d3cHM3C .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-XjAAJ7fe8d3cHM3C .node .label{text-align:center;fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .node.clickable{cursor:pointer}#mermaid-svg-XjAAJ7fe8d3cHM3C .arrowheadPath{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-XjAAJ7fe8d3cHM3C .flowchart-link{stroke:#333;fill:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-XjAAJ7fe8d3cHM3C .edgeLabel rect{opacity:0.9}#mermaid-svg-XjAAJ7fe8d3cHM3C .edgeLabel span{color:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-XjAAJ7fe8d3cHM3C .cluster text{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-XjAAJ7fe8d3cHM3C .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-XjAAJ7fe8d3cHM3C text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .actor-line{stroke:grey}#mermaid-svg-XjAAJ7fe8d3cHM3C .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .sequenceNumber{fill:#fff}#mermaid-svg-XjAAJ7fe8d3cHM3C #sequencenumber{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C #crosshead path{fill:#333;stroke:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .messageText{fill:#333;stroke:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-XjAAJ7fe8d3cHM3C .labelText,#mermaid-svg-XjAAJ7fe8d3cHM3C .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .loopText,#mermaid-svg-XjAAJ7fe8d3cHM3C .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-XjAAJ7fe8d3cHM3C .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-XjAAJ7fe8d3cHM3C .noteText,#mermaid-svg-XjAAJ7fe8d3cHM3C .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-XjAAJ7fe8d3cHM3C .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-XjAAJ7fe8d3cHM3C .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-XjAAJ7fe8d3cHM3C .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .section{stroke:none;opacity:0.2}#mermaid-svg-XjAAJ7fe8d3cHM3C .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-XjAAJ7fe8d3cHM3C .section2{fill:#fff400}#mermaid-svg-XjAAJ7fe8d3cHM3C .section1,#mermaid-svg-XjAAJ7fe8d3cHM3C .section3{fill:#fff;opacity:0.2}#mermaid-svg-XjAAJ7fe8d3cHM3C .sectionTitle0{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .sectionTitle1{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .sectionTitle2{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .sectionTitle3{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-XjAAJ7fe8d3cHM3C .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .grid path{stroke-width:0}#mermaid-svg-XjAAJ7fe8d3cHM3C .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-XjAAJ7fe8d3cHM3C .task{stroke-width:2}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText:not([font-size]){font-size:11px}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-XjAAJ7fe8d3cHM3C .task.clickable{cursor:pointer}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText0,#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText1,#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText2,#mermaid-svg-XjAAJ7fe8d3cHM3C .taskText3{fill:#fff}#mermaid-svg-XjAAJ7fe8d3cHM3C .task0,#mermaid-svg-XjAAJ7fe8d3cHM3C .task1,#mermaid-svg-XjAAJ7fe8d3cHM3C .task2,#mermaid-svg-XjAAJ7fe8d3cHM3C .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutside0,#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutside2{fill:#000}#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutside1,#mermaid-svg-XjAAJ7fe8d3cHM3C .taskTextOutside3{fill:#000}#mermaid-svg-XjAAJ7fe8d3cHM3C .active0,#mermaid-svg-XjAAJ7fe8d3cHM3C .active1,#mermaid-svg-XjAAJ7fe8d3cHM3C .active2,#mermaid-svg-XjAAJ7fe8d3cHM3C .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-XjAAJ7fe8d3cHM3C .activeText0,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeText1,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeText2,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeText3{fill:#000 !important}#mermaid-svg-XjAAJ7fe8d3cHM3C .done0,#mermaid-svg-XjAAJ7fe8d3cHM3C .done1,#mermaid-svg-XjAAJ7fe8d3cHM3C .done2,#mermaid-svg-XjAAJ7fe8d3cHM3C .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-XjAAJ7fe8d3cHM3C .doneText0,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneText1,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneText2,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneText3{fill:#000 !important}#mermaid-svg-XjAAJ7fe8d3cHM3C .crit0,#mermaid-svg-XjAAJ7fe8d3cHM3C .crit1,#mermaid-svg-XjAAJ7fe8d3cHM3C .crit2,#mermaid-svg-XjAAJ7fe8d3cHM3C .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCrit0,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCrit1,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCrit2,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCrit0,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCrit1,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCrit2,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-XjAAJ7fe8d3cHM3C .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-XjAAJ7fe8d3cHM3C .milestoneText{font-style:italic}#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCritText0,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCritText1,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCritText2,#mermaid-svg-XjAAJ7fe8d3cHM3C .doneCritText3{fill:#000 !important}#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCritText0,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCritText1,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCritText2,#mermaid-svg-XjAAJ7fe8d3cHM3C .activeCritText3{fill:#000 !important}#mermaid-svg-XjAAJ7fe8d3cHM3C .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-XjAAJ7fe8d3cHM3C g.classGroup text .title{font-weight:bolder}#mermaid-svg-XjAAJ7fe8d3cHM3C g.clickable{cursor:pointer}#mermaid-svg-XjAAJ7fe8d3cHM3C g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-XjAAJ7fe8d3cHM3C g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-XjAAJ7fe8d3cHM3C .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-XjAAJ7fe8d3cHM3C .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .dashed-line{stroke-dasharray:3}#mermaid-svg-XjAAJ7fe8d3cHM3C #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C .commit-id,#mermaid-svg-XjAAJ7fe8d3cHM3C .commit-msg,#mermaid-svg-XjAAJ7fe8d3cHM3C .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-XjAAJ7fe8d3cHM3C g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-XjAAJ7fe8d3cHM3C g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-XjAAJ7fe8d3cHM3C g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-XjAAJ7fe8d3cHM3C .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-XjAAJ7fe8d3cHM3C .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-XjAAJ7fe8d3cHM3C .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-XjAAJ7fe8d3cHM3C .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-XjAAJ7fe8d3cHM3C .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-XjAAJ7fe8d3cHM3C .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-XjAAJ7fe8d3cHM3C .edgeLabel text{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-XjAAJ7fe8d3cHM3C .node circle.state-start{fill:black;stroke:black}#mermaid-svg-XjAAJ7fe8d3cHM3C .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-XjAAJ7fe8d3cHM3C #statediagram-barbEnd{fill:#9370db}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-state .divider{stroke:#9370db}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-XjAAJ7fe8d3cHM3C .note-edge{stroke-dasharray:5}#mermaid-svg-XjAAJ7fe8d3cHM3C .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-XjAAJ7fe8d3cHM3C .error-icon{fill:#522}#mermaid-svg-XjAAJ7fe8d3cHM3C .error-text{fill:#522;stroke:#522}#mermaid-svg-XjAAJ7fe8d3cHM3C .edge-thickness-normal{stroke-width:2px}#mermaid-svg-XjAAJ7fe8d3cHM3C .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-XjAAJ7fe8d3cHM3C .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-XjAAJ7fe8d3cHM3C .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-XjAAJ7fe8d3cHM3C .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-XjAAJ7fe8d3cHM3C .marker{fill:#333}#mermaid-svg-XjAAJ7fe8d3cHM3C .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-XjAAJ7fe8d3cHM3C {color: rgba(0, 0, 0, 0.75);font: ;}

组装数据
导出

组装数据: 包括excel中表头、数据及样式
导出: 文件流

easyexcel 表头及数据

官方文档总结的都是经典~

表头: 分为固定表头和动态表头,然后再可以继续划分简单版本和复杂版本,其中复杂版本类似有三四级表头(以前写poi硬编码写到爆炸=_=||)~ 示例如下(图片来源):

数据: 随表头变更

表头

简单

固定表头,可声明一个实体类进行定义,如下:

@Data
public class TitleData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;
}

动态表头,只能自己手动写代码进行定义,如下:

// 外层数组,一个值代表一列
List<List<String>> headList = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
head0.add("字符串标题");
headList.add(head0);List<String> head1 = new ArrayList<String>();
head1.add("日期标题");
headList.add(head1);List<String> head2 = new ArrayList<String>();
head2.add("数字标题");
headList.add(head2);

合并

@Data
public class ComplexHeadData {@ExcelProperty({"主标题", "字符串标题"})private String string;@ExcelProperty({"主标题", "日期标题"})private Date date;@ExcelProperty({"主标题", "数字标题"})private Double doubleData;
}

web项目导出方式

web项目一般有两种导出方式:

  • 提供下载链接(异步):先生成excel并上传至oss/文件服务器,返回文件链接给前端,由前端自行下载
  • 文件流(同步):生成excel并塞入response流中

本文主要关注文件流方式,示例代码如下:

// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());

实践出真知

简单动态表头案例

本案例比较简单,根据请求参数time来动态定义表头和创建数据,并以文件流方式返回给前端。 效果如下:

pom中添加依赖:

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.7</version>
</dependency>

业务逻辑代码如下:

@RestController
public class ResultController {@PostMapping(value = "/export")public void export(@RequestParam Integer time) {try {HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();response.setHeader("Content-Disposition", "attachment; filename=export.xlsx");// 响应类型,编码response.setContentType("application/vnd.ms-excel;charset=utf-8");response.setCharacterEncoding("utf-8");EasyExcel.write(response.getOutputStream()).head(getHead(time)).sheet("数据").doWrite(getData(time));} catch (IOException e) {log.error("导出问卷数据失败!错误信息为:{}", e.getMessage());e.printStackTrace();}}/*** 获取excel标题栏(姓名、手机号、提交时间)* @param questionnaireId* @return*/private List<List<String>> getHead(Integer time) {// 外层数组,一个值代表一列List<List<String>> headList = new ArrayList<List<String>>();List<String> nameList = new ArrayList<String>();nameList.add("姓名");headList.add(nameList);List<String> telList = new ArrayList<String>();telList.add("手机号");headList.add(telList);List<String> submitDTList = new ArrayList<String>();submitDTList.add("提交时间");headList.add(submitDTList);for (int i = 0 ; i < time ; i ++ ) {List<String> list = new ArrayList<String>();list.add("动态标题" + i);headList.add(list);}return headList;}/*** 获取excel表格数据* @return*/private List<List<Object>> getData(Integer time) {// 将填写结果 + 提交时间合并为一行数据List<List<Object>> resultList = new ArrayList<List<Object>>();for (int i = 0 ; i < 3 ; i ++ ) {List<Object> list = new ArrayList<Object>();list.add("花卷" + i);list.add("1347000000" + i);list.add("2022-01-18 14:54:00");for (int j = 0 ; j < time ; j ++ ) {list.add("动态内容" + j);}resultList.add(list);}return resultList;}}

遇到的问题

前端联调时excel无法打开

问题描述: 后台用postman调试都ok,能正常打开excel!但是前端调试时下载的excel提示有破损,无法打开!!!
Tips: 勇敢(不怕死)的质疑前端,你代码有BUG!
解决方案: 前端需在request和response中添加responseType: blob设置

以下伪代码,请重点关注responseType设置即可

  1. 前端request应该设置responseType为arraybuffer或blob
return request({url: '/platform/export',
method: 'post',
responseType: 'blob',
headers: {'Content-Type': 'application/x-www-form-urlencoded'
},
data: qs.stringify(data)})
  1. 前端以blob格式接收response,并设置type为application/msexcel
handleExport(){exportData({id: this.id}).then(res => {if(res){const fileName = this.name + '.xlsx';var blob = new Blob([res], {type: "application/msexcel;charset=utf-8",});const URL = window.URL || window.webkitURL;const downloadElement = document.createElement("a");const href = URL.createObjectURL(blob); // 创建下载的链接downloadElement.href = href;downloadElement.download = fileName; // 下载后文件名document.body.appendChild(downloadElement);downloadElement.click(); // 点击下载document.body.removeChild(downloadElement); // 下载完成移除元素URL.revokeObjectURL(href); // 释放掉blob对象}})
},

下载文件接口有时返回文件流有时返回json的情况

测试小姐姐提了个单,token超时后,点击下载按钮还是能正常导出,excel内容是后端认证系统返回的错误码json串 =_=|| ,网上查找一番也找大佬们讨论了下,对于将文件流封装成系统设定的统一返回json方式不可取,最后抱着前端小姐姐的细腿求解决喽
解决方法:前端获取response后根据 content-type进行区分
网上参考文档

未完待续......

springboot easyexcel 导出excel案例及文件无法打开相关推荐

  1. springboot整合easyexcel 导入导出excel案例及文件无法打开

    前端请求 vue3+axios+typescript downloadByUrlStream({url:process.env.VUE_APP_API_URL1+"/MeshDevice/u ...

  2. swagger easyExcel导出Excel文件打不开,文件损坏

    alibaba/easyexcel文件导出 swagger easyExcel导出Excel文件打不开,文件损坏 文件下载打不开,将文件输出到本地发现可以打开,而且swagger下载的文件大小比本地文 ...

  3. Java 使用EasyExcel导出excel文件

    Java 使用EasyExcel导出excel文件 一.引入pom依赖 二.导出实体 三. 生成excelController 四.效果 一.引入pom依赖 <dependency>< ...

  4. easyexcel导出excel,大数据量100万以内分页查询zip格式导出

    easyexcel导出excel,大数据量100万以内分页查询zip格式导出 准备工作 整体思路 controller层 service层 mapper层 VO 表结构 测试 备注 easyExcel ...

  5. springboot项目导出excel 合并单元格表格

    springboot项目导出excel 合并单元格表格 导出效果 业务controller 业务数据 业务实体类 注解MyExcel.java 注解 MyExcels 导出工具类MyExcelUtil ...

  6. POI封装工具easyexcel导出EXCEL表样式设置

    POI封装工具easyexcel导出EXCEL表样式设置 java中对Office操作比较好的工具是POI,但POI在导出数据量较大的情况下很容易因内存占用过大,而出错,阿里巴巴推出的easyexce ...

  7. 将页面中表格数据导出excel格式的文件(vue)

    近期由于项目需要,需要将页面中的表格数据导出excel格式的文件,折腾了许久,在网上各种百度,虽然资料不少,但是大都不全,踩了许多坑,总算是皇天不负有心人,最后圆满解决了. 1.安装相关依赖(npm安 ...

  8. Java导出Excel表格出现文件损坏异常解决方案

    Java导出Excel表格出现文件损坏异常解决方案 问题出现 问题出现 本人遇到这个问题,由于是第一次见,感觉无从下手.但是导出功能很常见,做的也很多,只有这个出现了文件损坏,那很可能是代码写的有问题 ...

  9. 安卓导出Excel,txt文件工具类

    开始 安卓开发中,有时候会遇到到处文件的需求,尤其是平板上的开发,这个需求更为普遍,本文记录导出excel,txt文件的方法,并提供工具类,抛砖引玉,让大家遇到类似需求的时候,处理起来更为顺手. 导出 ...

  10. Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略)

    Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略) 适用于多张表(只查单表数据就用创建对象那种方法) Controller @RequestMapping(value = ...

最新文章

  1. c语言课程设计商品销售系统,c语言课程设计商品销售管理系统.pdf
  2. 获取AFP共享的文件夹及其权限
  3. NHibernate简介
  4. keras从入门到放弃(二)多项回归
  5. javaweb学习总结(六):Servlet开发(二)
  6. WCF中使用控件的委托,线程中的UI委托
  7. Java 注解学习笔记
  8. FreeBSD 11.0-发布公告
  9. 测试专家谈IT从业人员修炼之道
  10. 程序员必看—程序员如何高效提升自己?
  11. micropython常用模块-Python时间模块之datetime
  12. QQ/微信表情代码表
  13. Linux服务器校准时间
  14. 我的世界装mod要下java_【新人必看教程】我的世界HMCL下载安装mod模组
  15. 干货| 机器学习模型与算法最全分类汇总!
  16. 关于node.js,dataStr的undefined的问题
  17. 阅读高效能人士七个习惯
  18. Onlyoffice安装教程
  19. 移动端字体加粗的解决方案
  20. java list逆序_Java使用ListIterator逆序ArrayList

热门文章

  1. 全国地级市坐标、名称、编码获取 / 全球城市坐标位置
  2. 复合线转权属线lisp_三权发证中使用MAPGIS CASS如何应用复合线 简单、快速生成集体土地所有权权属线 -...
  3. 3D开源游戏引擎(遵循BSD和MIT)
  4. 弱电设计:智能建筑设计标准GB50314-2015,pdf版本
  5. web前端三大主流框架分析对比
  6. 2020五一建模:C题 饲料混合加工问题 题解
  7. 2023考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
  8. Windows10电脑重置后右键没有nvidia控制面板的问题
  9. java学生宿舍管理系统,来了就点个赞再走呗,即将毕业的兄弟有福了
  10. JDK11下载与安装 win10 64位