Here's the method to upload the file:
@RequestMapping(consumes = "multipart/form-data", method = RequestMethod.POST,
value = "/scan", produces = MediaType.APPLICATION_JSON_VALUE)
public String scan(MultipartFile file){
//code
}
Bean configuations:
@Bean
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("500MB");
factory.setMaxRequestSize("500MB");
return factory.createMultipartConfig();
}
pom.xml:
<parent>
<groupId>org.springframework.boot\</groupId>
<artifactId\>spring-boot-starter-parent\</artifactId>
<version>1.1.8.RELEASE\</version>
</parent>
Request:
POST /scan HTTP/1.1
Host: localhost:9080
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="file"; filename="generate.png"
Content-Type: image/png
----WebKitFormBoundaryE19zNvXGzXaLvS5C
- When run with spring boot 1.1.8, it works fine. Method parameter is correctly bound to the value.
- When run with any other version (tried with 1.2.0, 1.2.3), method parameter is always set to null. If I modify the method to include Request param like below:
public String scan(@RequestParam("file") MultipartFile file){
It throws an exception saying 'Required MultipartFile parameter 'file' is not present'.
I am running my spring boot app with embedded tomcat.
Comment From: wilkinsona
The problem's specific to the use of CommonsMultipartResolver
. Removing the bean and using the auto-configured StandardServletMultipartResolver
or explicitly declaring a StandardServletMultipartResolver
bean works around the problem.
Comment From: wilkinsona
It only works in 1.1.8 because of the bug reported in #1857. That bug causes the CommonsMultipartResolver
bean that's named multipartResolver
to be overridden with Boot's own multipartResolver
bean that's a StandardServletMultipartResolver
.
Comment From: wilkinsona
The problem is that, when you use CommonsMultipartResolver
, it's vital that the multipart request is processed before any request parameters are read. Spring Boot auto-configures HiddenHttpMethodFilter
and, as noted in its javadoc, it "needs to run after multipart processing in case of a multipart POST request, due to its inherent need for checking a POST body parameter". This can be achieved by declaring a MultipartFilter
bean that's ordered to run before HiddenHttpMethodFilter
and giving it a filterMultipartResolver
bean to use:
@Bean
public CommonsMultipartResolver filterMultipartResolver() {
return new CommonsMultipartResolver();
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
return new MultipartFilter();
}
Comment From: darshanmehta10
Hi Wilkinsona, Thanks for the detailed explanation. Will try with StandardServletMultipartResolver bean. Cheers
Comment From: fxulusoy
@wilkinsona I have the same problem. My method parameter is always set to null. As you said, I set order for the multipartFilter bean but it did not help. I see that HiddenHttpMethodFilter
is always called before MultipartFilter
. I am using Spring Boot version 1.3.0.RELEASE and Java based config. How can I set the order that HiddenHttpMethodFilter
comes after MultipartFilter
?
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSizePerFile(52428800);
return resolver;
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
@RequestMapping(value = "/{userId}", method = RequestMethod.POST)
@ResponseBody
public FileTransport createAsset(@PathVariable("userId") Long userId,
MultipartFile file) throws IOException {
//return fileService.create(userId, file);
return new FileTransport();
}
Comment From: wilkinsona
@fxulusoy The order of HiddenHttpMethodFilter
has changed. You need to order your MultipartFilter
with a value that's less than -10000.
Comment From: fxulusoy
@wilkinsona Are you sure that will change the order? Because I have tried that and HiddenHttpMethodFilter
is still called before MultipartFilter
. file argument is still null.
Comment From: wilkinsona
It should work. Perhaps you can share a complete sample project that shows the problem as it's hard to know what's wrong from the little you've shared thus far. A question on Stack Overflow with a complete, minimal example of the problem would be ideal. You can use the spring-boot
tag to make sure that we see it.
Comment From: wilkinsona
@fxulusoy I see you've already posted to Stack Overflow: http://stackoverflow.com/questions/37951569/multipartfile-is-null-when-i-use-commonsmultipartresolver-in-my-spring-boot-app. Please don't cross-post, particularly without making it clear that you have done so, as it just wastes people's time.
Comment From: sebzimmermann
I'm having the same issue using these settings:
@Bean
public CommonsMultipartResolver filterMultipartResolver() {
return new CommonsMultipartResolver();
}
@Bean
@Order(-11111) // same with @Order(0)
public MultipartFilter multipartFilter() {
return new MultipartFilter();
}
Uploading a file resolves in:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
After removing the CommonsMultipartResolver Bean the upload works.
I'm using Release 1.4.0. Any hints on how to fix this?
Comment From: wilkinsona
@sebzimmermann Please use Stack Overflow for questions
Comment From: jaymmodi
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipart = new CommonsMultipartResolver();
multipart.setMaxUploadSize(3 * 1024 * 1024);
return multipart;
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
This worked for me. Thanks @wilkinsona
Comment From: zhaozhi406
http://stackoverflow.com/questions/22723871/required-multipartfile-parameter-file-is-not-present/29411814#29411814 this solution works for me, and it's very easy !
Comment From: brenuart
Just for the record, Tomcat (version 8 at least) is already using Apache Commons File Upload behind its Servlet 3 implementation. The library is repackaged under org.apache.tomcat.util.http.fileupload
.
SpingBoot's default is to rely on the container to process uploads - so you already get Commons FileUpload... I'm just wondering why you are willing to change that...
Comment From: philwebb
Thanks @brenuart, we'll document that suggestCommonsMultipartResolver
should not be used.
Comment From: lucasdeassis
I have tried without CommonsMultipartResolver
and it works fine on spring boot v2.02. I ran into an issue while testing against it using MockMvc and MockMvcRequestBuilders.multipart
though. After many tries, the only thing that helped was looking at a MockPart example.
Comment From: xak2000
Unfortunately, StandardServletMultipartResolver
doesn't support defining different max file size etc for different URLs.
This is clearly mentioned in the docs:
Configuration settings such as maximum sizes or storage locations need to be applied at that servlet registration level; Servlet 3.0 does not allow for them to be set at the MultipartResolver level.
So if I need to set different max-file-size
, max-request-size
etc based on some condition (e.g. URL), I still need to use CommonsMultipartResolver
in combination with custom MultipartFilter
(overriding it's lookupMultipartResolver
method). Am I right?
If am I right, then I want to ask why there is warning in spring-boot docs, introduced in the last commit of this issue (4f51a83):
It is recommended to use the container’s built-in support for multipart uploads rather than introducing an additional dependency such as Apache Commons File Upload.
Is it just a general recommendation to use built-in functionality to not reinvent the wheel (when it satisfies), or there are more practical reasons to not use CommonsMultipartResolver
with custom MultipartFilter
?
Comment From: wilkinsona
As it says, it’s a recommendation, and nothing more than that. If it was a requirement it would say so.
Comment From: huaxne
@wilkinsona Dear wilkinsona My code to upload file works well in SpringBoot version 2.1.6, but can not work in version 2.2.5. code like this:
@PostMapping("/upload")
public Response uploadDept(@RequestParam(value = "file") MultipartFile excelFile){}
error like below:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:199) ~[spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
Is there any change about MultipartFile
in 2.25?
Comment From: wilkinsona
@huaxne I don't believe so, no. If you believe you had found a bug, please open a new issue and provide a minimal sample that reproduces the problem. Otherwise, if you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.