java后台生成中文名称可下载文件,vue3前端通过axios来实现下载。
java后端的文件生成文件的代码,这是是用来hutool生成excel文件
@ResponseBody
@RequestMapping(value = "/downloadDataQuery")
public void downloadDataQuery(HttpServletRequest request, HttpServletResponse response, @RequestBody ReqDataQueryVo reqDataQueryVo) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String chineseFileName = "导出数据.xlsx";
String encodedFileName = URLEncoder.encode(chineseFileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName);
//response.setHeader("Content-Disposition","attachment;filename=export.xlsx");
// 需要加上下面这个,不然跨域的头拿不到这个Content-Disposition信息
response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
OutputStream out = response.getOutputStream();
log.info("downloadDataQuery reqDataQueryVo:" + reqDataQueryVo);
try {
List<DataQueryRespVo> dataQueryRespVoList = dataQueryService.queryByReqDataQuery(reqDataQueryVo);
List<DataQueryRespExportVo> dataQueryRespExportVoList = objectMapper.convertValue(dataQueryRespVoList, objectMapper.getTypeFactory().constructCollectionType(List.class, DataQueryRespExportVo.class));
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(dataQueryRespExportVoList, true);
writer.flush(out, true);
writer.close();
IoUtil.close(out);
} catch (Exception exception) {
log.error(exception.getMessage());
}
}
这里是vue3前端下载文件的代码,主要是要支持utf8编码。
let handleOnExport2 = () => {
loading.value = true;
console.log("导出2: ");
let reqObject = reactive({...toRefs(queryParams)});
console.log("queryParams:"+JSON.stringify(queryParams));
console.log("reqObject: "+JSON.stringify(reqObject));
downloadDataQuery(reqObject).then((res)=>{
console.log(res);
let { data, headers } = res;
console.log("headers:"+headers);
console.log("headers:"+JSON.stringify(headers));
if (res.data instanceof Blob) {
console.log("ok1");
let blob = new Blob([res.data], {type: headers['content-type']});
// 检查Content-Disposition头来获取文件名
let contentDisposition = res.headers['content-disposition'];
let fileName = 'downloaded-file.xls'; // 默认文件名
if (contentDisposition) {
// 使用正则表达式匹配filename*部分
let utf8FileNameMatch = contentDisposition.match(/filename\*=(UTF-8''|utf-8''|utf8''|UTF8'')(.+)/);
if (utf8FileNameMatch && utf8FileNameMatch[2]) {
// 提取出并解码UTF-8编码的文件名
fileName = decodeURIComponent(utf8FileNameMatch[2].replace(/['"]/g, ''));
} else {
// 如果没有filename*,尝试从传统的filename中提取(可能未编码)
let simpleFileNameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
if (simpleFileNameMatch != null && simpleFileNameMatch[1]) {
fileName = simpleFileNameMatch[1].replace(/['"]/g, '');
}
}
}
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
//link.download = '导出.xlsx';
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
loading.value = false;
} else {
console.log("ok2");
console.error(res.message || '下载失败!');
}
}).catch((err,res)=>{
console.error(err || '下载失败!');
});
}
上面使用了api目录下的情况接口方法;api接口文件内容如下
// 查询方法
export function downloadDataQuery(data) {
return request({
url: '/proddata/downloadDataQuery',
method: 'post',
data: data,
responseType: 'blob'
})
}
如果不喜欢这种。可以使用下面比较原始的方式。
let handleOnExport2 = () => {
loading.value = true;
console.log("导出2: ");
let reqObject = reactive({...toRefs(queryParams)});
console.log("queryParams:"+JSON.stringify(queryParams));
console.log("reqObject: "+JSON.stringify(reqObject));
axiosInstance.post("/proddata/downloadDataQuery",reqObject,{responseType: 'blob'}).then((res)=>{
console.log(res);
let { data, headers } = res;
console.log("headers:"+headers);
console.log("headers:"+JSON.stringify(headers));
if (res.data instanceof Blob) {
console.log("ok1");
let blob = new Blob([res.data], {type: headers['content-type']});
// 检查Content-Disposition头来获取文件名
let contentDisposition = res.headers['content-disposition'];
let fileName = 'downloaded-file.xls'; // 默认文件名
if (contentDisposition) {
// 使用正则表达式匹配filename*部分
let utf8FileNameMatch = contentDisposition.match(/filename\*=(UTF-8''|utf-8''|utf8''|UTF8'')(.+)/);
if (utf8FileNameMatch && utf8FileNameMatch[2]) {
// 提取出并解码UTF-8编码的文件名
fileName = decodeURIComponent(utf8FileNameMatch[2].replace(/['"]/g, ''));
} else {
// 如果没有filename*,尝试从传统的filename中提取(可能未编码)
let simpleFileNameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
if (simpleFileNameMatch != null && simpleFileNameMatch[1]) {
fileName = simpleFileNameMatch[1].replace(/['"]/g, '');
}
}
}
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
//link.download = '导出.xlsx';
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
loading.value = false;
} else {
console.log("ok2");
console.error(res.message || '下载失败!');
}
}).catch((err,res)=>{
console.error(err || '下载失败!');
});
}