java - 如何以西里尔文返回下载的文件名?
问题描述
我想返回带有西里尔文名称的文件。
现在我的代码看起来像:
@GetMapping("/download/{fileId}")
public void download(@PathVariable Long fileId, HttpServletResponse response) throws IOException {
...
response.setContentType("txt/plain" + "; charset=" + "WINDOWS-1251");
String filename = "русское_слово.txt";
response.addHeader("Content-disposition", "attachment; filename=" + filename);
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
//...
}
当我从浏览器访问 url 时 - 浏览器为我提供了将文件保存在磁盘上的对话框,但它显示_
而不是西里尔字母。
看起来是响应标头编码问题:
{
"access-control-expose-headers": "Content-disposition",
"content-disposition": "attachment; filename=???_??.txt",
"date": "Fri, 28 Dec 2018 15:53:44 GMT",
"transfer-encoding": "chunked",
"content-type": "txt/plain;charset=WINDOWS-1251"
}
我尝试了以下选项:
response.addHeader("Content-disposition", "attachment; filename*=UTF-8''" + filename);
和以下:
response.addHeader("Content-disposition", "attachment; filename*=UTF-8''" + URLEncoder.encode(filename,"UTF-8"));
但这无济于事
我该如何解决这个问题?
解决方案
如果您在 Spring 5+ 上,您可以使用ContentDisposition
:
String filename = "русское слово.txt";
ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
.filename(filename, StandardCharsets.UTF_8)
.build();
System.out.println(contentDisposition.toString());
输出:
attachment; filename*=UTF-8''%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%BE%D0%B5%20%D1%81%D0%BB%D0%BE%D0%B2%D0%BE.txt
ContentDisposition
隐藏了您尝试做的所有工作(请参阅其toString
实现):
if (this.filename != null) {
if (this.charset == null || StandardCharsets.US_ASCII.equals(this.charset)) {
sb.append("; filename=\"");
sb.append(this.filename).append('\"');
}
else {
sb.append("; filename*=");
sb.append(encodeHeaderFieldParam(this.filename, this.charset));
}
}
此外,如果您不想HttpServletRequest
直接处理,则可以返回ResponseEntity
:
@RequestMapping("/")
public ResponseEntity<Resource> download() {
HttpHeaders httpHeaders = new HttpHeaders();
String filename = "русское_слово.txt";
ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
.filename(filename, StandardCharsets.UTF_8)
.build();
httpHeaders.setContentDisposition(contentDisposition);
return new ResponseEntity<>(new ByteArrayResource(new byte[0]),
httpHeaders, HttpStatus.OK);
}
推荐阅读
- r - 闪亮的应用程序使用查询字符串中的默认值?
- javascript - 如何在 Sequelize Model 中创建方法?
- c - 如何使用开关来偏移 for 循环的开始?
- web-scraping - 如何在本地更改没有 VPN/代理的 IP 地址?
- node.js - Heroku Redis 使用 nodejs 开发
- concurrency - 与 Ben Ari 的频道就餐哲学家陷入僵局?
- c++ - 如何调用在一个类中创建然后传递给另一个类的 c++ 函数指针?
- javascript - 将 HTML 表单提交到带有 JS 验证的 PHP 文件
- python - 有什么方法可以改变 PyGame 中标题的颜色吗?
- delphi - Delphi,表单发布,阻止Application.MessageBox执行