7.2 文件下载

7.2 文件下载

示例: Spring MVC的文件下载

可能很多读者会觉得, 文件下载太简单, 直接在页面给出一个超链接, 该链接的href属性等于要下载文件的文件名, 不就可以实现文件下载了吗? 这样做大部分时候的确可以实现文件下载, 但如果该文件的文件名为中文文件名, 在某些早期的浏览器上就会导致下载失败( 使用最新的FirefoxOperaChromeSafari都可以正常下载文件名为中文的文件)。
Spring MVC提供了一个ResponseEntity类型, 使用它可以很方便地定义返回的BodyBuilderHttpHeadersHttpStatus

download方法

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
@GetMapping(value = "/download")
public ResponseEntity<byte[]> download(HttpServletRequest request,
@RequestParam("filename") String filename,
@RequestHeader("User-Agent") String userAgent) throws Exception
{
// 下载文件路径
String path = request.getServletContext().getRealPath("/images");
// 构建File
File file = new File(path + File.separator + filename);
// ok表示Http协议中的状态 200
BodyBuilder builder = ResponseEntity.ok();
// 内容长度
builder.contentLength(file.length());
// application/octet-stream : 二进制流数据(最常见的文件下载)。
builder.contentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用URLDecoder.decode对文件名进行解码
filename = URLEncoder.encode(filename, "UTF-8");
// 设置实际的响应文件名,告诉浏览器文件要用于【下载】、【保存】attachment 以附件形式
// 不同的浏览器,处理方式不同,要根据浏览器版本进行区别判断
if (userAgent.indexOf("MSIE") > 0)
{
// 如果是IE,只需要用UTF-8字符集进行URL编码即可
builder.header("Content-Disposition",
"attachment; filename=" + filename);
} else
{
// 而FireFox、Chrome等浏览器,则需要说明编码的字符集
// 注意filename后面有个*号,在UTF-8后面有两个单引号!
builder.header("Content-Disposition",
"attachment; filename*=UTF-8''" + filename);
}
return builder.body(FileUtils.readFileToByteArray(file));
}

代码分析

download处理方法接收到页面传递的文件名filename后, 使用Apache Commons FileUpload组件的FileUtils读取项目的images文件夹下的该文件, 并将其构建成ResponseEntity对象返回客户端下载。
使用ResponseEntity对象, 可以很方便地定义返回的BodyBuilderHttpHeadersHttpStatusBodyBuilder对象用来构建返回的BodyHttpHeaders类型代表的是Http协议中的头信息;
HttpStatus类型代表的是Http协议中的状态。 上面代码中的MediaType, 代表的是Internet Media Type, 即互联网媒体类型, 也叫作MIME类型。
Http协议消息头中, 使用Content- Type来表示具体请求中的媒体类型信息。 有关BodyBuilderMediaTypeHttpStatus类的详细信息参考Spring MVCAPI文档。

测试

单击下载页面的超链接, 显示文件正在下载。 结果如图 7.3 所示。
单击“ 浏览” 按钮, 选择下载文件保存的路径, 然后单击“ 确定” 按钮, 文件即会被顺利下载并保存。