Spring MVC 文件上传和下载

本文最后更新于:2024年9月8日 晚上

Spring MVC 文件上传和下载

  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver,因此,Spring MVC的文件上传还需要依赖Apache Commons FileUpload的组件。
  • 前端响应要求:为了能上传文件,必须将表单的method设置为POST,并将Content-Type设置为multipart/form-data,只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。

Content-Type:属性

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
  • 注意:form表单中的enctype对应HTTP请求中的Content-Type
1
2
3
4
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
  • 一旦设置了Content-Typemultipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。

文件上传

Controller

  • 采用transferTo()方法保存文件。
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
@RestController
public class FileController {

@Value("${file.upload-path}")
private String uploadPath;

@PostMapping("/upload")
public Result upload(MultipartFile uploadFile) throws IOException {
if (uploadFile == null) {
return ResultUtil.error("上传文件为空");
}
// 在 uploadPath 文件夹中通过日期对上传的文件归类保存。
SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
String datePath = sdf.format(new Date());
File folder = new File(uploadPath + datePath);
if (!folder.isDirectory() && !folder.mkdirs()) {
return ResultUtil.error("文件目录创建失败");
}
// 对上传的文件重命名,避免文件重名。
String originalName = uploadFile.getOriginalFilename();
if (StringUtils.isEmpty(originalName)) {
return ResultUtil.error("文件名为空");
}
String newName = UUID.randomUUID() + originalName.substring(originalName.lastIndexOf("."));
// 保存文件。
uploadFile.transferTo(new File(folder, newName));
// 返回上传文件的访问路径。
String fullPath = uploadPath + datePath + newName;
return ResultUtil.success("文件上传成功", fullPath);
}
}

文件下载

  • 使用ResponseEntity<T>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RequestMapping("/download")
public ResponseEntity<byte[]> test(String fileName,HttpServletRequest request) throws IOException {
// 获得下载文件所在路径可以指向系统中的任意一个有权访问的路径。
String downLoadPath = request.getServletContext().getRealPath("/download");

// 创建要下载的文件对象。
File file = new File(downLoadPath,fileName);

// 处理一下要下载的文件名字,解决中文乱码。
String downFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");

// 创建响应头信息的对象。
HttpHeaders headers = new HttpHeaders();
// 设置下载的响应头信息,通过浏览器响应正文的内容是用户要下载的,不用浏览器解析。
headers.setContentDispositionFormData("attachment", downFileName);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

// 通过响应内容,响应头信息,响应状态来构建一个响应对象并返回。
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}