-
multipart格式的数据会将一个form拆分成多个part,每个part对应一个输入域
-
(1) Spring中解析Multipart交给了MultipartResolver接口的实现类
(2) Spring内置了 MultipartResolver的实现类, CommonsMultipartResolver 和 StandardServletMultipartResolver,更优的选择是StandardServletMultipartResolver
-
CommonsMultipartResolver的配置 P209
-
StandardServletMultipartResolver的配置
(1) 首先声明为bean
(2) 然后
1 实现 WebApplicationInitializer接口的customizeRegistration()方法中调用setMultipartConfig方法
或
2 在 AnnotationConfigDispatcherServletInitializer(DispatcherServlet)重载customizeRegistration()方法
示例
public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { ... @Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig(new MultipartConfigElement("/", 2097152, 4194304, 0)); } }
其中,MultipartConfigElement的构造函数public MultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold)的几个参数分别代表:上传路径, 文件的最大容量(byte), 整个multipart请求的最大容量(byte), 写入到磁盘上的最小文件大小
-
表单form中的multipart
(1) 示例
<html xmlns:th="http://www.thymeleaf.org"> ... <body> ... <div id="content"> <h1>Register</h1> <form method="POST" th:object="${spitter}" enctype="multipart/form-data"> <div class="errors" th:if="${#fields.hasErrors('*')}"> <ul> <li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect </li> </ul> </div> <label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>: <input type="text" th:field="*{firstName}" th:class="${#fields.hasErrors('firstName')}? 'error'"/> <br/> <label th:class="${#fields.hasErrors('lastName')}? 'error'">Last Name</label>: <input type="text" th:field="*{lastName}" th:class="${#fields.hasErrors('lastName')}? 'error'"/> <br/> <label th:class="${#fields.hasErrors('email')}? 'error'">Email</label>: <input type="text" th:field="*{email}" th:class="${#fields.hasErrors('email')}? 'error'"/> <br/> <label th:class="${#fields.hasErrors('username')}? 'error'">Username</label>: <input type="text" th:field="*{username}" th:class="${#fields.hasErrors('username')}? 'error'"/> <br/> <label th:class="${#fields.hasErrors('password')}? 'error'">Password</label>: <input type="password" th:field="*{password}" th:class="${#fields.hasErrors('password')}? 'error'"/> <br/> <label>Profile Picture</label>: <input type="file" name="profilePicture" accept="image/jpeg,image/png,image/gif"/> <br/> <input type="submit" value="Register"/> </form> </div> ... </body> </html>
(2) <form method="POST" th:object="${spitter}" enctype="multipart/form-data">
form中的enctype属性设置为multipart/form-data,告诉浏览器以multipart形式提交表单,而不是以表单数据的形式提交。这样的结果是每个 <.input> 元素会对应一个part
(3) <input type="file" name="profilePicture" accept="image/jpeg,image/png,image/gif"/>
这个input的元素type为file,可以让用户选择要上传的文件;accept属性限定了上传文件的类型;name和Controller中要处理的参数名对应
-
Controller中处理multipart数据
(1) 示例 FileUploadController.java
@Controller @RequestMapping("/fileupload") public class FileUploadController { @RequestMapping(method = RequestMethod.GET) public String uploadForm() { return "uploadForm"; } @RequestMapping(method = RequestMethod.POST) public String processUpload( @RequestPart("file") MultipartFile file) { return "redirect:/"; } }
(2) 添加 @RequestPart注解
@RequestPart("file") MultipartFile file 代表从form中读取name为file的文件
(3) MultipartFile接口有很多好用的方法 P212
例如 transferTo()方法可以把文件保存到本地
(4) 替代MultipartFile的方案是使用Part,具体操作和MultipartFile类似,只不过不需要配置MultipartResolver
示例 SpitterController.java
@Controller @RequestMapping("/spitter") public class SpitterController { ... @RequestMapping(value = "/register", method = POST) public String processRegistration( @RequestPart(value = "profilePicture") MultipartFile profilePicture, @Valid Spitter spitter, Errors errors) throws IllegalStateException, IOException { if (errors.hasErrors()) { return "registerForm"; } spitterRepository.save(spitter); profilePicture.transferTo(new File("/" + spitter.getUsername() + ".png")); return "redirect:/spitter/" + spitter.getUsername(); } }
网友评论