介绍
本文会简单地做一个将列表数据导出excel功能的例子,excel框架将采用EasyExcel的,前端使用vue,后端使用Java。
EasyExcel是一个基于Java的简单、省内存的读写Excel的阿里巴巴开源项目。在尽可能节约内存的情况下支持读写百M的Excel。官方文档
代码
后端
依赖
<!-- 阿里巴巴 easyExcel依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
导出的model类,使用了@ExcelIgnoreUnannotated和@ExcelProperty两个EasyExcel的注解。具体的注释可以查看文档,进行配置。
@Data
@ExcelIgnoreUnannotated //没有注解的字段都不转换
public class Book{
@ExcelProperty("编号")//设置了表中列的名称
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ExcelProperty("书名")
private String name;
@ExcelProperty("封面图片")
private String image;
@ExcelProperty("作者")
private String author;
}
导出excel的接口
@GetMapping("/book/export")
public void export(HttpServletResponse response) throws IOException {
//获取需要导出的数据
List<Book> dataList = bookService.list();
//excel文件名
final String FILENAME = "图书信息";
//sheetName
final String SHEETNAME = "用户信息表";
//获取model对象类
Class book = Book.class;
try {
//表头样式策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//设置头居中
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//内容策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
//设置 水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
//初始化表格样式
HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
// response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode(FILENAME, "UTF-8").replaceAll("\\+", "%20");
//响应首部 Access-Control-Expose-Headers 就是控制“暴露”的开关,它列出了哪些首部可以作为响应的一部分暴露给外部。
//此处设置了开放Content-Disposition,前端可获取该响应参数获取文件名称
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream(), book).autoCloseStream(Boolean.FALSE)
.registerWriteHandler(horizontalCellStyleStrategy).sheet(SHEETNAME).doWrite(dataList);
} catch (IOException e) { //下载失败情况的处理
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = MapUtils.newHashMap();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
前端
导出excel的接口调用
this.$axios({
method: "get",
url: "/book/export",
responseType: "blob", // 表明返回服务器返回的数据类型
})
.then((res) => {
// 处理返回的文件流
let blob = new Blob([res.data], { type: res.data.type });
//获取fileName,截取content-disposition的filename;按=分割,取最后一个
const fileName = decodeURI(res.headers['content-disposition'].split("=")[1], "UTF-8");
let downloadElement = document.createElement("a");
let href = window.URL.createObjectURL(blob); //创建下载的链接
downloadElement.href = href;
downloadElement.download = fileName; //下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); //点击下载
document.body.removeChild(downloadElement); //下载完成移除元素
window.URL.revokeObjectURL(href); //释放blob
this.$message.success("[图书信息]已成功导出!");
})
.catch(function(error) {
// 请求失败处理
console.log(error);
});
实现结果
excel导出成功
Fiddler抓包显示的接口数据
导出的excel数据
本文参考
springboot+easyExcel+vue导出excel
axios无法获取响应头headers的Content-Disposition字段
header中Content-Disposition的作用与使用方法