大腿的博客

excel导出,文件名称中文乱码问题

字数统计: 633阅读时长: 2 min
2019/02/24 Share

记录一个excel导出遇见的中文名称的问题

场景

接到项目需要有excel的导入导出功能,基于poi实现还是挺简单的,文件的导入导出都已经实现,但是导出给前台的文件名称总是乱码,一开始以为是我后台的问题,我找解决方法找了两天但是都不外乎就那几个。最后发现是前台的代码问题…

后台导出代码

controller接口

1
2
3
4
5
6
7
8
9
10
11
12
@ApiOperation(value = "导出模板", notes = "导出模板")
@GetMapping(value = "export-template")
public void exportTemplate(HttpServletRequest request, HttpServletResponse response) {
// 设置的中文文件名
String fileName = "模板.xls";
// 设置excel的头
String[] title = {"姓名", "性别", "年龄"};
// 自定义的excel工具,创建工作簿。
WorkBook wb = ExcelUtil.createExcel(fileName, title);
// 导出流
ExcelUtil.binaryOut(request, response, wb, fileName);
}

这里重点在binaryOut()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class ExcelUtil {
...
public static void binaryOut(HttpServletRequest request, HttpServletResponse response, WorkBook wb, String fileName) {
try (OutputString os = response.getOutputStream()) {
// 设置响应头
setResponseHeader(request, response, fileName);
wb.write(os);
wb.close();
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void setResponseHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
String userAgent = request.getHeader("USER-AGENT");
String finalFileName = null;
try {
// 处理不同浏览器的文件名乱码问题
try {
if (org.apache.commons.lang3.StringUtils.contains.contains(userAgent, "MSIE")) {
// IE
finalFileName = URLEncoder.encode(fileName, "UTF8");
} else if (org.apache.commons.lang3.StringUtils.contains.contains(userAgent, "Mozilla")) {
// 火狐,谷歌
finalFileName = new String(fileName.getBytes(), "ISO-8859-1");
} else {
// 其他
finalFileName = URLEncoder.encode(fileName, "UTF8");
}
} catch (UnsupportedEncodingException ue) {
ue.printStackTrace();
}
response.setContentType("applicaction/vnd.ms-excel");
// 设置文件名
response.setHeader("Content-Disposition", "attachment; filename=" + finalFileName);
} catch (Exception e) {
e.printStackTrace();
}
}
...
}

至此,导出的功能完成了,并且在本地测试都成功,文件名也是预设中文名。但是前端调用接口输出的文件就不是我们的中文。问题出在了前端的处理方式上。

前端代码

前端一开始的处理方式

1
2
3
4
5
6
export(res) {
...
let blob = new Blob([res], {type: "application/vnd.ms-excel"});
  let objectUrl = URL.createObjectURL(blob);
  window.location.href = objectUrl;
}

res是请求后台得到的response。前端这里直接将response的流拿出来生成blob,再将blob转文件。这种方式下载的文件只有文件内容。如果代码不去手动设置文件名称的话,浏览器会自动给生成的文件一个序列号,后缀名是头里面设置的Contant-Type对应的后缀名。

代码使用

1
window.location.href = "host:port/export-template"

直接用浏览器打开下载的api就可以了。至于为什么浏览器会直接下载还有不知道。

CATALOG
  1. 1. 场景
  2. 2. 后台导出代码
  3. 3. 前端代码