文章目录
- 背景介绍
- 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设置即可)
- 前端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)})
- 前端以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案例及文件无法打开相关推荐
- springboot整合easyexcel 导入导出excel案例及文件无法打开
前端请求 vue3+axios+typescript downloadByUrlStream({url:process.env.VUE_APP_API_URL1+"/MeshDevice/u ...
- swagger easyExcel导出Excel文件打不开,文件损坏
alibaba/easyexcel文件导出 swagger easyExcel导出Excel文件打不开,文件损坏 文件下载打不开,将文件输出到本地发现可以打开,而且swagger下载的文件大小比本地文 ...
- Java 使用EasyExcel导出excel文件
Java 使用EasyExcel导出excel文件 一.引入pom依赖 二.导出实体 三. 生成excelController 四.效果 一.引入pom依赖 <dependency>< ...
- easyexcel导出excel,大数据量100万以内分页查询zip格式导出
easyexcel导出excel,大数据量100万以内分页查询zip格式导出 准备工作 整体思路 controller层 service层 mapper层 VO 表结构 测试 备注 easyExcel ...
- springboot项目导出excel 合并单元格表格
springboot项目导出excel 合并单元格表格 导出效果 业务controller 业务数据 业务实体类 注解MyExcel.java 注解 MyExcels 导出工具类MyExcelUtil ...
- POI封装工具easyexcel导出EXCEL表样式设置
POI封装工具easyexcel导出EXCEL表样式设置 java中对Office操作比较好的工具是POI,但POI在导出数据量较大的情况下很容易因内存占用过大,而出错,阿里巴巴推出的easyexce ...
- 将页面中表格数据导出excel格式的文件(vue)
近期由于项目需要,需要将页面中的表格数据导出excel格式的文件,折腾了许久,在网上各种百度,虽然资料不少,但是大都不全,踩了许多坑,总算是皇天不负有心人,最后圆满解决了. 1.安装相关依赖(npm安 ...
- Java导出Excel表格出现文件损坏异常解决方案
Java导出Excel表格出现文件损坏异常解决方案 问题出现 问题出现 本人遇到这个问题,由于是第一次见,感觉无从下手.但是导出功能很常见,做的也很多,只有这个出现了文件损坏,那很可能是代码写的有问题 ...
- 安卓导出Excel,txt文件工具类
开始 安卓开发中,有时候会遇到到处文件的需求,尤其是平板上的开发,这个需求更为普遍,本文记录导出excel,txt文件的方法,并提供工具类,抛砖引玉,让大家遇到类似需求的时候,处理起来更为顺手. 导出 ...
- Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略)
Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略) 适用于多张表(只查单表数据就用创建对象那种方法) Controller @RequestMapping(value = ...
最新文章
- c语言课程设计商品销售系统,c语言课程设计商品销售管理系统.pdf
- 获取AFP共享的文件夹及其权限
- NHibernate简介
- keras从入门到放弃(二)多项回归
- javaweb学习总结(六):Servlet开发(二)
- WCF中使用控件的委托,线程中的UI委托
- Java 注解学习笔记
- FreeBSD 11.0-发布公告
- 测试专家谈IT从业人员修炼之道
- 程序员必看—程序员如何高效提升自己?
- micropython常用模块-Python时间模块之datetime
- QQ/微信表情代码表
- Linux服务器校准时间
- 我的世界装mod要下java_【新人必看教程】我的世界HMCL下载安装mod模组
- 干货| 机器学习模型与算法最全分类汇总!
- 关于node.js,dataStr的undefined的问题
- 阅读高效能人士七个习惯
- Onlyoffice安装教程
- 移动端字体加粗的解决方案
- java list逆序_Java使用ListIterator逆序ArrayList
热门文章
- 全国地级市坐标、名称、编码获取 / 全球城市坐标位置
- 复合线转权属线lisp_三权发证中使用MAPGIS CASS如何应用复合线 简单、快速生成集体土地所有权权属线 -...
- 3D开源游戏引擎(遵循BSD和MIT)
- 弱电设计:智能建筑设计标准GB50314-2015,pdf版本
- web前端三大主流框架分析对比
- 2020五一建模:C题 饲料混合加工问题 题解
- 2023考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
- Windows10电脑重置后右键没有nvidia控制面板的问题
- java学生宿舍管理系统,来了就点个赞再走呗,即将毕业的兄弟有福了
- JDK11下载与安装 win10 64位