1、文件上传

(1)创建html文件表单 user_info.html

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form th:action="@{/upload}" method="post" enctype="multipart/form-data">
  9. <input type="text" name="username" class="form-control" placeholder="用户名" autofocus>
  10. <input type="password" name="password" class="form-control" placeholder="密码">
  11. <input type="file" name="header_url" placeholder="头像">
  12. <input type="file" name="photos" placeholder="生活照片" multiple>
  13. <button type="submit" >提交</button>
  14. </form>
  15. </body>
  16. </html>

(2)配置路由器

@Slf4j
@Controller
public class UserController {

    @GetMapping("/user/save")
    public String saveUserInfoPage(){
        return "file/user_info";
    }

    @PostMapping("/upload")
    public String saveUserInfo(@RequestParam("username") String username,
                               @RequestParam("password") String password,
                               @RequestPart("header_url") MultipartFile headerUrl,
                               @RequestPart("photos") MultipartFile[] photos) throws IOException {

        log.info("用户名:{},密码:{},头像文件名称:{},生活照几张:{}",username,password,headerUrl.getName(),photos.length);
        if (!headerUrl.isEmpty()){
            headerUrl.transferTo(new File("/Users/djy/Desktop/tmp/"+headerUrl.getOriginalFilename()));
        }
        for (MultipartFile file : photos){
            if (!file.isEmpty()){
                file.transferTo(new File("/Users/djy/Desktop/tmp/"+file.getOriginalFilename()));
            }
        }
        return "redirect:/index.html";
    }

}

(3)默认文件单个最大才1兆,单次请求文件总大小10兆,不够用,所以修改文件上传大小

#修改单个最大文件上传尺寸
spring.servlet.multipart.max-file-size=10MB
#修改单个请求所有文件总和大小
spring.servlet.multipart.max-request-size=100MB

2、文件上传原理

1、自动配置都存在MultipartAutoConfiguration中

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {
  • 配置了文件上传解析器StandardServletMultipartResolver

      @Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
      @ConditionalOnMissingBean(MultipartResolver.class)
      public StandardServletMultipartResolver multipartResolver() {
          StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
          multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
          return multipartResolver;
      }
    
  • 步骤

    • 1、请求进来使用文件上传解析器(isMultipart)判断并调用resolveMultipart封装成MutipartHttpServletRequest请求文件上传请求

      @Override
      public boolean isMultipart(HttpServletRequest request) {
         return StringUtils.startsWithIgnoreCase(request.getContentType(),
                 (this.strictServletCompliance ? MediaType.MULTIPART_FORM_DATA_VALUE : "multipart/"));
      }
      
      @Override
      public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
         return new StandardMultipartHttpServletRequest(request, this.resolveLazily);
      }
      
    • 2、通过RequestPartMethodArgumentResolver来解析image.png

    • 深处解析代码就是通过从提前封装好的MultipartHttpServletRequest中获取MultipartFile文件。
      List<MultipartFile> files = multipartRequest.getFiles(name);