Georgios Syngouroglou
Georgios Syngouroglou

Reputation: 19944

Multipart Request with MultipartFile as Optional Field - Spring MVC

I am using Spring MVC on a J2EE Web application.
I have created a method that bounds the request body to a model like the above

@RequestMapping(value = "/", method = RequestMethod.POST, produces = "application/json")
public AModel createEntity(@Valid @ModelAttribute MyInsertForm myInsertForm) {
    // coding..
}  

Everything are working great and when i include a property of type MultipartFile in the MyEntityForm, then i have to make the request with content type "multipart/form-data".
Also, everything are working great with this scenario too.

The problem i am facing is that i would like to have the MultipartFile property as optional.
When a client request include a file my method works great but when a client request does not include a file spring throws a

HTTP Status 500 - Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly

Is there any way to solve this issue without creating two methods on my controller (one with a MultipartFile and another without)?

Upvotes: 10

Views: 12788

Answers (3)

tk_
tk_

Reputation: 17318

I had the same issue and just adding the required=false worked for me; because, I don't send a file all the time. Please find the sample code below,

@RequestMapping(value = "/", method = RequestMethod.POST, produces = "application/json")
public AModel createEntity(@Valid @ModelAttribute MyInsertForm myInsertForm, @RequestParam(value ="file", required=false) MultipartFile file) {
    // coding..
}  

Upvotes: 16

Georgios Syngouroglou
Georgios Syngouroglou

Reputation: 19944

When you wish to send one or more files using HTTP, you have to use multipart request. This means that the body of the request will be like the above,

-----------------------------9051914041544843365972754266 Content-Disposition: form-data; name="text"

text default -----------------------------9051914041544843365972754266 Content-Disposition: form-data; name="file1"; filename="a.txt" Content-Type: text/plain

Content of a.txt.

-----------------------------9051914041544843365972754266 Content-Disposition: form-data; name="file2"; filename="a.html" Content-Type: text/html

When you wish to send only data (and not files) you can send them as json, key-value pairs etc.

Spring framework uses the @ModelAttribute annotation when you wish to map a multipart request to an object. When you have a normal key-value request, you use the @RequestBody annotation. Thus, you can't have the MultipartFile optional, because you have to use different annotations. Using two different methods, one per request type, solves the issue. Example,

@RequestMapping(value = "/withFile", method = RequestMethod.POST, produces = "application/json")
public ReturnModel updateFile(@ModelAttribute RequestModel rm) {
    // do something.
}

@RequestMapping(value = "/noFile", method = RequestMethod.PUT, produces = "application/json")
public ReturnModel updateJson(@RequestBody RequestModel rm) {
    // do something else.
}

Upvotes: -1

Juned Ahsan
Juned Ahsan

Reputation: 68715

Give a try by adding

(required=false)

to multipart property in method signature.

Upvotes: 3

Related Questions