SpringBoot解决下载接口文件名中文乱码问题的3种方法
问题场景
在Spring或SpringBoot开发的项目中,下载文件接口经常会出现在下载文件时,文件名为中文或者包含中文时,可能会出现乱码的问题。
问题分析
一、页面与服务器编码不一致
文件名乱码问题,常见原因是编码不一致。即服务器使用的编码方式与客户端(即Java程序)使用的编码方式不一样时,就会出现中文字符乱码。如果Java程序使用的是默认的ISO-8859-1编码方式,而服务器使用的是UTF-8编码方式,那么下载的文件名就会出现乱码现象。
二、Content-Disposition头部信息问题
如果开发的服务接口没有正确设置Content-Disposition头部信息,浏览器将无法正确解析文件名,就会导致下载的文件名乱码 ,特别是文件名为中文或者包含中文时。其中Content-Disposition头部信息就是用于告诉浏览器如何处理下载的文件。
解决方法
方式一:设置合适的编码方式
解决编码不一致问题的方法是将Java程序的编码方式设置为与服务器一致的方式。我们可以对文件名称使用 URL编码方式进行处理 。
String fileName = "测试下载文件.doc";//解决下载文件时文件名乱码问题byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);fileName = new String(fileNameBytes, 0, fileNameBytes.length,
StandardCharsets.ISO_8859_1);long contentLength = file.length();HttpHeaders httpHeaders = new HttpHeaders();httpHeaders.setContentType(MediaType.valueOf(contentType));httpHeaders.setContentDispositionFormData("attachment", fileName);httpHeaders.setContentLength(contentLength);
方式二:设置正确的Content-Disposition头部信息
针对解决缺少Content-Disposition头部信息的情况,合适的方法是在服务器端设置正确的头部信息。使用setContentType方法设置了Content-Type为application/octet-stream,表示下载的是二进制文件。然后,我们使用setHeader方法设置了Content-Disposition头部信息,其中filename参数指定了下载的文件名。
String fileName = "下载文件.doc";
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment; filename=\"" + fileName + "\"");
方式三:同时解决编码和头部信息问题
文件名称使用URL编码处理,对于文件名种有空格, 就会被截断的情况。不能直接把空格替换成%20, 因为%会被url编码转成%25。建议的方式是先使用URL编码, 再使用+号进行替换。
public void download(HttpServletResponse response){String fileName = "下载文件";// 文件名先进行url编码, 避免乱码问题// 把+用%20进行替换fileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");response.setContentType("application/octet-stream");// 注意是 filename*=utf-8''response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".doc");}
重点关注参数:attachment;filename*=utf-8''