后端controller层:
@PostMapping("/listExport")
public void maEmployeeListExport(//这里返回值必须为空,如果设返回了result结果类,返回给前端会报错
@RequestParam(value = "belong", required = false) String belong,
@RequestParam(value = "role", required = false) String role,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "phone", required = false) String phone,
HttpServletResponse response){
//第一步创建一个webbook,对应一个Excel文件
HSSFWorkbook wb = new HSSFWorkbook();
wb = maEmployeeService.maEmployeeListExport(belong, role, name, phone);//这里调用service层相关方法,主要是为了生成一个workbook,具体service层可根据自己需求编写
//将文件传给前端
try {
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
String filename = "filename="
+ URLEncoder.encode("excle文件.xlsx", "UTF-8") + ";";
response.setHeader("Content-Disposition", filename);
try {
wb.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
前端vue
1、使用vue-elementui,前端会接受统一格式的返回值,如以下格式:
主要代码位于:\src\utils\request.js,但是后端返回值为一个数据流,无法返回正常的结果集,所以需要修改这个文件中的代码,思路为判断为文件流格式直接将获取到的结果返回,具体如下:
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response.data
//!!!!!修改的部分就是在这里增加一个if语句,如果为判断返回值为文件流直接跳过校验
if (res instanceof Blob) {
return Promise.resolve(response)//这里要返回response,而不是response.data,后续需要从response中获取headers
}
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
2、请求excel导出接口,位于src\api\目录下:
exportMaEmployeeList(searchModel) {
return request({
url: '/sys/maEmployee/listExport',
method: 'post',
params: {
belong: searchModel.belong,
role: searchModel.role,
name: searchModel.name,
phone: searchModel.phone,
},
responseType: 'blob'//这里需要设置成blob类型
});
},
3、接受后端的文件流并导出,位于src\views的vue文件:
exportMaEmployeeList() {
maEmployeeApi.exportMaEmployeeList(this.searchModel).then(response => {
var blob = new Blob([response.data], {
type: "application/vnd.ms-excel;charset=utf-8",
});
//获取文件名
var temp = response.headers["content-disposition"];//这里有个bug,后端写的是Content-Disposition,但是log打印response,变成了content-disposition。
var fileName = decodeURIComponent(temp.split("filename=")[1]); // 中文需要转码 (前端乱码)
var name = fileName.split(";")[0]; //切割成文件名
var url = window.URL.createObjectURL(blob);
//使用a标签拼接字符串
var aLink = document.createElement("a");
aLink.style.display = "none";
aLink.download = name;
aLink.href = url;
document.body.appendChild(aLink);
aLink.click();
});
},
总结
excel导出后端返回值需要改成void,然后需要更改前端request.js对于返回结果的校验,
强行使用结果集返回前端,会导致后端报错,因为返回结果集是json格式,httpservletresponse返回了文件流,可能相当于在返回文件流后又返回一个json导致了报错,如果你有好方法解决这个问题请告诉我