无法使用 Spring Boot 1.2.8 配置 CommonsMultipartResolver

Cannot configure CommonsMultipartResolver with Spring Boot 1.2.8

我正在尝试在我的 Spring 启动应用程序中使用 CommonsMultipartResolver。我不能使用 StandardServletMultipartResolver,因为我想处理异常(例如超过文件大小)。

我已经建立了对 commons-fileupload 的依赖。我的 spring 配置是:

    @Autowired
    private MultipartProperties multipartProperties = new MultipartProperties();

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        return this.multipartProperties.createMultipartConfig();
    }

    @Bean
    public MultipartResolver multipartResolver() {
        LOG.debug("initializing MultipartResolver");
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        return multipartResolver;
    }

    @Bean
    public FilterRegistrationBean multipartFilterRegistrationBean() {
        final MultipartFilter multipartFilter = new MultipartFilter();
        final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(multipartFilter);
        multipartFilter.setMultipartResolverBeanName("multipartResolver");
        filterRegistrationBean.setOrder(OrderedHiddenHttpMethodFilter.DEFAULT_ORDER-1);
        return filterRegistrationBean;
    }

当我设置 MultipartFilterHiddenHttpMethodFilter 之前执行时,我得到一个 IOException:

Caused by: java.io.IOException: Missing content for multipart request
at org.eclipse.jetty.util.MultiPartInputStreamParser.parse(MultiPartInputStreamParser.java:491)
at org.eclipse.jetty.util.MultiPartInputStreamParser.getParts(MultiPartInputStreamParser.java:400)
at org.eclipse.jetty.server.Request.getParts(Request.java:2139)
at org.eclipse.jetty.server.Request.extractMultipartParameters(Request.java:385)
... 35 common frames omitted

否则,我会收到请求中不存在零件参数的异常。

我认为我需要禁用 servlet 3.0 对多部分请求的处理,但我不知道如何在 spring 启动时执行此操作。

Spring 启动自动配置一个 MultipartConfigElement,参见 https://spring.io/guides/gs/uploading-files/ 只需从类路径中删除 commons-fileupload

请注意,HiddenHttpMethodFilter 需要在多部分处理后执行,如 spring 文档所述:

NOTE: This filter needs to run after multipart processing in case of a multipart POST request, due to its inherent need for checking a POST body parameter. So typically, put a Spring MultipartFilter before this HiddenHttpMethodFilter in your web.xml filter chain.

问题是由 DefaultMultipartHttpServletRequestHiddenHttpMethodFilter 调用的 getParameter 上抛出异常引起的,因为流已在 MultipartFilter 中处理:

@Override
protected void doFilterInternal(HttpServletRequest request, >HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

  String paramValue = request.getParameter(this.methodParam);
  if ("POST".equals(request.getMethod()) && >StringUtils.hasLength(paramValue)) {
      String method = paramValue.toUpperCase(Locale.ENGLISH);
      HttpServletRequest wrapper = new >HttpMethodRequestWrapper(request, method);
      filterChain.doFilter(wrapper, response);
  }
  else {
      filterChain.doFilter(request, response);
  }
}

我的解决方案是禁用 MultipartAutoConfiguration,不定义 MultipartConfigElement bean 以禁用 servlet 3.0 多部分解析并且不使用 MultipartFiler.

现在的配置如下所示:

@Autowired
private MultipartProperties multipartProperties = new MultipartProperties();

@Bean
public MultipartResolver multipartResolver() {
    LOG.debug("initializing MultipartResolver");
    MultipartConfigElement config = multipartProperties.createMultipartConfig();
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setResolveLazily(true);
    multipartResolver.setMaxUploadSize(config.getMaxRequestSize());
    multipartResolver.setMaxUploadSizePerFile(config.getMaxFileSize());
    return multipartResolver;
}

现在甚至可以在文件超过允许的最大大小时使用@ExceptionHandler 建议return 正确的 HTTP 代码。