赞
踩
一般导出流程图如下:
组装数据: 包括excel中表头、数据及样式
导出: 文件流
官方文档总结的都是经典~
表头: 分为固定表头和动态表头,然后再可以继续划分简单版本和复杂版本,其中复杂版本类似有三四级表头(以前写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项目一般有两种导出方式:
本文主要关注文件流方式,示例代码如下:
// 这里注意 有同学反应使用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; } }
问题描述: 后台用postman调试都ok,能正常打开excel!但是前端调试时下载的excel提示有破损,无法打开!!!
Tips: 勇敢(不怕死)的质疑前端,你代码有BUG!
解决方案: 前端需在request和response中添加responseType: blob
设置
(以下伪代码,请重点关注responseType设置即可)
responseType为arraybuffer或blob
return request({
url: '/platform/export',
method: 'post',
responseType: 'blob',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: qs.stringify(data)
})
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对象 } }) },
测试小姐姐提了个单,token超时后,点击下载按钮还是能正常导出,excel内容是后端认证系统返回的错误码json串 =_=|| ,网上查找一番也找大佬们讨论了下,对于将文件流封装成系统设定的统一返回json方式不可取,最后抱着前端小姐姐的细腿求解决喽
解决方法:前端获取response后根据 content-type
进行区分
网上参考文档
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。