工作中遇到的小坑,记录一下
Hutool的官方文档有给出详细的excel文件导出工具类(ExcelWriter),然而实际使用中,有些地方容易踩坑,记录一下方便对照。
首先是SpringBoot的后端,我用的是写出到客户端下载的方式,输入需要的年份year和月份month,HttpServletResponse也是必须的。
@ApiOperation("表格导出接口")
@GetMapping ("/export")
public void export(@RequestParam String month, @RequestParam String year, HttpServletResponse response) throws IOException {
// 用个List<Map>装表格的所有内容
ArrayList<Map<String, Object>> rows = new ArrayList<>();
// 拿取表格里需要的数据
List<ExportVO> result = conferenceService.getExportVO(month, year);
// 拼接上列明。我这里用的最土的方法,很不优雅别学我
for(int i = 0; i < result.size(); i++){
Map<String, Object> row = new LinkedHashMap<>();
row.put("会议类型", result.get(i).getConferenceType());
row.put("会议日期", result.get(i).getUsingDate());
row.put("会议名称", result.get(i).getConfereceName());
row.put("主办部门", result.get(i).getMainDept());
row.put("责任人", result.get(i).getContacts());
row.put("参会人员范围", result.get(i).getScope());
row.put("备注", result.get(i).getOtherNeeds());
rows.add(row);
}
// 通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter(true);
// 合并单元格后的标题行
writer.merge(6, year+"年-"+month+"月统计表"); //lastColumn = 列数-1
// 一次性写出内容
writer.write(rows, true);
// 微调一下每个列的宽度
writer.setColumnWidth(0,12);
writer.setColumnWidth(1,16);
writer.setColumnWidth(2,24);
writer.setColumnWidth(3,34);
writer.setColumnWidth(4,10);
writer.setColumnWidth(5,200);
writer.setColumnWidth(6,8);
// 此处的response.setContentType 和教程里的不同
response.setContentType("application/octet-stream");
// filename就是表格的名字,这个无所谓,反正前端还会重命名
response.setHeader("Content-Disposition","attachment;filename=test.xlsx");
// 输出流
ServletOutputStream servletOutputStream = response.getOutputStream();
writer.flush(servletOutputStream,true);
// 关闭writer,释放内存
writer.close();
// 关闭输出Servlet流
IoUtil.close(servletOutputStream);
}
注意,第21行那个,ExcelWriter writer = ExcelUtil.getWriter(true),第一个小坑点,如果要导出的是xlsx,这个括弧里的true是一定要加的!!
第35行的response.setContentType("application/octet-stream"),与教程里的不同,我用教程里的会报错,故选用此。
然后是前端,先写个api.js
//引入axios
import axios from 'axios'
//请求延时(毫秒数,如果请求话费超过了'timeout'的时间,请求将被中断)
axios.defaults.timeout 100000
//导出exce1
export const export2 params =>{
return axios.get(`后端接口的地址`,{params params,responseType:'blob'})
}
这里axios一定要加那个responseType:'blob',不然前端拿到的流下下来的文件会有格式问题!
之后就写相关的method
methods:{
//导出excel的method
exportExcel(){
const params = {
month: this.month,
year : this.year
}
export2(params).then(
(res)=>{
let blob = new Blob([res.data], {type: "application/vnd.ms-excel",});
// application/vnd.ms-excel为excel类型文档
let fileName = this.year+"年-"+this.month+"月会议统计表.xlsx";
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// IE
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
let objectUrl = (window.URL || window.webkitURL).createObjectURL(
blob
);
let downFile = document.createElement("a");
downFile.style.display = "none";
downFile.href = objectUrl;
downFile.download = fileName; // 下载后文件名
document.body.appendChild(downFile);
downFile.click();
document.body.removeChild(downFile); // 下载完成移除元素 // window.location.href = objectUrl
window.URL.revokeObjectURL(objectUrl); // 只要映射存在,Blob就不能进行垃圾回收,因此一旦不再需要引用,就必须小心撤销URL,释放掉blob对象。
}
}
)
}
页面里直接用这个method就行了,需要注意的是第10行那里的new Blob 的type类型,需要的话对照着看
版权归原作者 泰兰纳斯 所有, 如有侵权,请联系我们删除。