在 启用 MultipartResolver 后,带有 multipart/form-data的 POST 请求的内容被解析并作为常规请求参数访问。下面的例子访问了一个普通的表单字段和一个上传的文件:
@Controllerpublic class FileUploadController {@PostMapping("/form")public String handleFormUpload(@RequestParam("name") String name,@RequestParam("file") MultipartFile file) {if (!file.isEmpty()) {byte[] bytes = file.getBytes();// store the bytes somewherereturn "redirect:uploadSuccess";}return "redirect:uploadFailure";}}
将参数类型声明为 List<MultipartFile>允许为同一参数名解析多个文件。
当 @RequestParam注解被声明为 Map<String, MultipartFile>或 MultiValueMap<String, MultipartFile>时,如果没有在注解中指定参数名称,那么该 map 将被填充为每个给定参数名称的多部件文件。
:::info
通过 Servlet 3.0 的多部件解析,你也可以声明 javax.servlet.http.Part 而不是 Spring 的 MultipartFile,作为方法参数或集合值类型。
:::
你也可以使用多部件内容作为数据绑定到 命令对象 的一部分。例如,前面的例子中的表单字段和文件可以是表单对象上的字段,如下例所示:
class MyForm {private String name;private MultipartFile file;// ...}@Controllerpublic class FileUploadController {@PostMapping("/form")public String handleFormUpload(MyForm form, BindingResult errors) {if (!form.getFile().isEmpty()) {byte[] bytes = form.getFile().getBytes();// store the bytes somewherereturn "redirect:uploadSuccess";}return "redirect:uploadFailure";}}
在 RESTful 服务场景中,多部件请求也可以从非浏览器客户端提交。下面的例子显示了一个带有 JSON 的文件:
POST /someUrlContent-Type: multipart/mixed--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7VpContent-Disposition: form-data; name="meta-data"Content-Type: application/json; charset=UTF-8Content-Transfer-Encoding: 8bit{"name": "value"}--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7VpContent-Disposition: form-data; name="file-data"; filename="file.properties"Content-Type: text/xmlContent-Transfer-Encoding: 8bit... File Data ...
你可以用 @RequestParam作为一个字符串来访问 「meta-data」部分,但你可能希望它从 JSON 中反序列化(与 @RequestBody类似)。使用@RequestPart注解,在用 HttpMessageConverter 进行转换后访问一个多部件。
@PostMapping("/")public String handle(@RequestPart("meta-data") MetaData metadata,@RequestPart("file-data") MultipartFile file) {// ...}
这里关于前端页面如何构造这个请求,可以参考笔者的另外一篇笔记
文件下载、上传、混合 JSON 提交
你可以将 @RequestPart与 javax.validation.Valid结合起来使用,或者使用 Spring 的 @Validated注解,这两种方法都会导致标准 bean 验证被应用。默认情况下,验证错误会导致 MethodArgumentNotValidException,它被转化为 400(BAD_REQUEST)响应。另外,你可以通过 Errors 或 BindingResult 参数在控制器中本地处理验证错误,如下面的例子所示:
@PostMapping("/")public String handle(@Valid @RequestPart("meta-data") MetaData metadata,BindingResult result) {// ...}
