问题描述
- 上传文件时抛出异常:
org.apache.catalina.connector.RequestFacade cannot be cast to org.springframeworkweb.multipart.MultipartHttpServletRequest - 原本以为前端使用FormData上传文件就会出现这个问题,后来自己验证时发现,正确使用FormData,后台进行强转也是没有问题,因为目前只会Ajax,所以用Ajax进行验证。
- 具体使用场景如下:
var formdata = new FormData($("#fileForm")[0]);
$.ajax({
url: "http://127.0.0.1:8081/demo/fileupload",
type: "post",
data: formdata,
cache: false, // 有说是为了应对IE8及之前版本的缓存情况
processData: false, // 不处理数据, 没有该项前端会报错, Uncaught TypeError: Illegal invocation
contentType: false, // 不设置内容类型, 没有该项后台会抛出异常RequestFacade cannot be cast to MultipartHttpServletRequest,该项表明ContentType:multipart/form-data
success: function (result) {
// ...
},
error: function () {
}
});
@PostMapping("/fileupload")
public void demo(HttpServletRequest request) {
MultipartHttpServletRequest params = (MultipartHttpServletRequest) request;
// ...
}
解决方法一
- 需要引入相应的jar包,包括commons-io和commons-fileuploade,否则抛ClassNotFoundException异常。
MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
MultipartHttpServletRequest mhsr = resolver.resolveMultipart(request);
MultipartFile file = mhsr.getMultiFileMap.get("file").get(0);
解决方法二
- 不需要引入引入其它jar包,必须使用支持Servlet3.0的容器。
MultipartResolver resovler = new StandardServletMultipartResolver();
MultipartHttpServletRequest mhsr = resovler.resolveMultipart(request);
MultipartFile file = mhsr.getMultiFileMap().get("file").get(0);
解决方法三
- 其实是方案二的配置方法,将StandardServlerMultipartResovler注册到容器中。
- SpringBoot使用CommonsMultipartResolver时有默认配置,不用再注册CommonsMultipartResolve,否则MultipartFile会接收不到文件。
@Configuration
public class MultipartFileUploadConfiguration {
@Bean
public MultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
return multipartResolver;
}
}
扩展
- SpringMVC提供CommonsMultipartResolver和StandardServletMultipartResolver两个MultipartResolver的实现用于处理multipart请求。
- 文件上传的大小默认配置是:每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb。所以会出现超出最大上传文件限制的情况。
- 通过配置文件修改上传文件限制,这里需要注意不同SpringBoot版本的配置略有区别。详情可见感谢Chopper_Tony的分享
#上传文件总的最大值
spring.servlet.multipart.max-request-size=10MB
#单个文件的最大值
spring.servlet.multipart.max-file-size=10MB
- 通过@Bean配置修改
@Configuration
public class MultipartFileUploadConfiguration {
@Bean
public MultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
return multipartResolver;
}
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//文件最大
factory.setMaxFileSize("102400KB"); //KB,MB
// 设置总上传数据总大小
factory.setMaxRequestSize("204800KB");
return factory.createMultipartConfig();
}
}
- 如果是非SpringBoot项目,使用XML文件配置的话,要注意CommonsMultipartResolver和StandardServletMultipartResolver的不同。
<!-- CommonsMultipartResolver采用的方式 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 限制所有上传文件的总共大小 -->
<property name="maxUploadSize" value="204800000" />
</bean>
<!-- StandardServletMultipartResolver采用的方式 -->
<servlet>
<servlet-name>fileUpload</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:[定义MultipartResovler的xml文件的相对路径]</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
<multipart-config>
<location>D:/temp/</location>
<max-file-size>102400000</max-file-size>
<max-request-size>204800000</max-request-size>
</multipart-config>
</servlet>
如果本文所述内容有误,欢迎并感谢指正。