如果下载的文件名包含中文,有时浏览器可能无法正确显示文件名,而会显示乱码或者一串数字和字母。这个问题可以通过设置Content-Disposition
响应头的filename
参数来解决,该参数可以指定要下载的文件名,并且支持URL编码。
下面是一个示例代码,演示了如何在Java Web中设置响应的文件名,以支持中文文件名的下载:
@GET
@Path("/download")
public Response downloadFile(@QueryParam("filename") String filename) throws UnsupportedEncodingException {
// 获取要下载的文件
File file = new File("/path/to/files/" + filename);
// 创建响应
ResponseBuilder responseBuilder = Response.ok(file);
// 设置文件名
String encodedFilename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
responseBuilder.header("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
return responseBuilder.build();
}
在上述示例中,downloadFile
方法使用@GET
和@Path
注解来定义一个RESTful Web服务,该服务接收一个filename
参数,表示要下载的文件名。该方法首先获取要下载的文件,然后创建一个响应,将文件作为响应的内容。
接着,将文件名进行URL编码。这里使用了filename.getBytes("UTF-8")
方法将原始文件名转换为UTF-8编码的字节数组,然后使用new String
构造方法将字节数组转换为ISO-8859-1编码的字符串。由于ISO-8859-1编码是浏览器默认的编码方式,因此使用这种方式可以确保浏览器能够正确显示文件名。
最后,使用responseBuilder.header
方法设置Content-Disposition
响应头,将编码后的文件名作为filename
参数传入。最终,使用responseBuilder.build
方法构建响应并返回。
如果文件名仍然出现乱码问题,可能是因为服务器端编码和浏览器端编码不一致导致的。你可以尝试如下方法解决:
java.net.URLEncoder.encode()
方法进行编码,例如:String encodedFilename = URLEncoder.encode(filename, "UTF-8");
responseBuilder.header("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
如果上述方法仍然无效,可能是文件名编码本身存在问题,可以考虑对文件名进行重命名,在重命名前将文件名进行URL编码,确保文件名编码正确。
前端解码
在 JavaScript 中,可以使用 decodeURIComponent()
函数对 URL 进行解码。该函数用于将 URL 中的编码的字符解码为它们原来的值。
下面是一个示例代码,演示如何使用 decodeURIComponent()
函数解码 URL:
let encodedUrl = "http%3A%2F%2Fexample.com%2Fpath%3Fquery%3D%E4%B8%AD%E6%96%87";
let decodedUrl = decodeURIComponent(encodedUrl);
console.log(decodedUrl);
// Output: http://example.com/path?query=中文
在上述示例代码中,使用了一个编码后的 URL,它包含了一些特殊字符和中文字符。然后,使用 decodeURIComponent()
函数对 URL 进行解码,并将解码后的 URL 打印出来。
需要注意的是,如果 URL 中包含的编码字符是不正确的,或者不完整的,那么 decodeURIComponent()
函数可能会抛出异常。此时需要确保 URL 编码的正确性。
如果要对整个 URL 进行解码,可以使用 decodeURI()
函数,它可以解码整个 URL,包括协议、主机名、路径和查询字符串等。例如:
let encodedUrl = "http%3A%2F%2Fexample.com%2Fpath%3Fquery%3D%E4%B8%AD%E6%96%87";
let decodedUrl = decodeURI(encodedUrl);
console.log(decodedUrl);
// Output: http://example.com/path?query=中文
使用 decodeURI()
函数可以方便地对整个 URL 进行解码,适用于需要还原整个 URL 的场景。
@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("网址备份_"+JWTUtils.getUserIdByHeader()+".xlsx", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename=" + fileName );
List data =new ArrayList<>();
for (int i = 0; i < 10000; i++) {
URLModel urlModel=new URLModel();
urlModel.setUrl("url"+i);
urlModel.setName("setName"+i);
urlModel.setWebCategoryName("setWebCategoryName"+i);
data.add(urlModel);
}
EasyExcel.write(response.getOutputStream(), URLModel.class).sheet("模板").doWrite(data );
}
const handleDownload = () => {
const fileUrl = '/api/download';
const requestOptions = {
method: 'GET',
headers: {
authorization: getAuthority(),
}
};
fetch(fileUrl, requestOptions)
.then(response => {
let filename = response.headers.get('content-disposition').split('filename=')[1];
filename = decodeURIComponent(filename);
response.blob().then(blob => {
const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
});
}