需求描述: 实现一个报表查询功能,可以根据查询条件导出Excel文件。
技术栈: SpringBoot 2.1.3 + Swagger 2.7.2 + poi 4.0.1
public void exportExcel(UserQuery query, HttpServletResponse response) {
// 1. 查询数据
List userStageList = sevice.getUserStageList(query);
// 2. 生成Excel
Workbook workbook = ExcelExportUtils.exportExcel(userStageList);
// 3. 设置response参数,可以打开下载页面
ServletOutputStream out = null;
try {
String fileName = "用户阶段详情.xlsx";
String encodeFileName = new String(StrUtil.bytes("用户阶段详情.xlsx", CharsetUtil.CHARSET_GBK), CharsetUtil.CHARSET_ISO_8859_1);
response.setHeader("Content-Disposition", "attachment; filename=" + encodeFileName);
response.setHeader("filename", URLEncoder.encode(fileName, CharsetUtil.UTF_8));
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel");
out = response.getOutputStream();
workbook .write(out);
out.flush();
} catch (Exception e) {
// 打印日志,抛出异常
} finally {
// 关闭IO
}
问题描述
接口写完之后,通过swagger和postman进行测试发现文件无法正常打开。
// 图一:下载
// 图二:打开文件
// 图三:点击“是”
问题定位:
- 起初以为是Jar包版本冲突,在分析之后,排除这种可能。
- 怀疑是内置Tomcat依赖版本问题,在更新版本以及替换成servlet-api之后,问题依然存在
- 找到《java通过poi生成excel并下载出现文件打不开、文件格式和文件扩展名无效问题的分析与解决》文章,可能是Swagger问题,于是使用其他方式,导出成功。
直接在浏览器中直接输入url的方式,就得到了正常的可打开且格式正确的excel
// 图4
使用F12,打开浏览器console方式,执行以下指令:
//触发方法下载后
var url = 'http://localhost:8088/api/download-file?userId=' + {id};
fetch(url,{
method: 'GET',
mode: 'cors', // no-cors, cors, *same-origin
headers: new Headers({
'Content-Type': 'application/json',
// 'Authorization': `Bearer ${token}`
})
}
).then(res => res.blob().then(blob => {
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
var filename = res.headers.get('content-disposition').split(';')[1].split('=')[1]
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
[POST]方式,无需修改代码
使用F12,打开浏览器console方式,执行以下指令:
//触发方法下载后
var url = 'http://localhost:8088/api/download-file';
fetch(url,{
method: 'POST',
mode: 'cors', // no-cors, cors, *same-origin
body: window.JSON.stringify(params),
headers: new Headers({
'Content-Type': 'application/json',
// 'Authorization': `Bearer ${token}`
})
}
).then(res => res.blob().then(blob => {
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
var filename = res.headers.get('content-disposition').split(';')[1].split('=')[1]
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
修改代码,使用Swagger测试
在api代码上增加以下注释:
@ApiOperation(value = "导出用户阶段详情", notes = "export", produces = "application/octet-stream")
@RequestMapping 里面也有produces 和consumes
produces ==> 指定返回值类型,不但可以设置返回值类型还可以设定返回值的字符编码
consumes ==> 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
加了上面得到注解后,对于那种查询一些数据,然后导出到excel 进行下载是可以正常打开的。



