chapter07_SpringMVC的高级技术_2_处理Multipart形式的数据

  • 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中的enctype属性设置为multipart/form-data,告诉浏览器以multipart形式提交表单,而不是以表单数据的形式提交。这样的结果是每个 <.input> 元素会对应一个part

    (3)

    这个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();
          }
      }
    

猜你喜欢

转载自blog.csdn.net/captxb/article/details/87879747