错误
当工程升级到SpringBoot2.1使用ServletFileUpload获取Request里面文件报错如下:
org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header is null
原因
首先需要了解的是SpringBoot2里自动装配了MultipartResolver
MultipartResolver
来自org.springframework.web.multipart
包下的MultipartResolver
提供解析包括文件上传在内的多部分请求策略。一种实现方式是基于Commons FileUpload
,另外则基于Servlet 3.0
的多部分请求解析。
启用多部分处理,需要在DispatcherServlet
Spring配置中声明一个名为multipartResolver
的MultipartResolver
bean。DispatcherServlet
检测到它并将其应用于传入的请求。当接收到一个content-type
是multipart/form-data
的POST请求时,解析程序将解析内容并将当前HttpServletRequest
包装为MultipartHttpServletRequest
,以提供对已解析部分的访问权限,此外将其作为请求参数公开。
而装配MultipartResolver的的配置是MultipartAutoConfiguration
MultipartAutoConfiguration
@Configuration
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class,
MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {
private final MultipartProperties multipartProperties;
public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
this.multipartProperties = multipartProperties;
}
@Bean
@ConditionalOnMissingBean({ MultipartConfigElement.class,
CommonsMultipartResolver.class })
public MultipartConfigElement multipartConfigElement() {
return this.multipartProperties.createMultipartConfig();
}
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
return multipartResolver;
}
可以看出MultipartAutoConfiguration配置类,默认加载的是StandardServletMultipartResolver
。
然而,我们往往会在项目中加入commons-fileupload
依赖,加载的是CommonsMultipartResolver。此时同时使用两个,会产生冲突
。
解决
1. 启动类排除
在启动类排除配置
@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
2. 配置文件禁用
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
3. 自定义文件解析对象
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
return resolver;
}