Multipart File upload Spring Boot
Solution 1
@RequestBody MultipartFile[] submissions
should be
@RequestParam("file") MultipartFile[] submissions
The files are not the request body, they are part of it and there is no built-in HttpMessageConverter
that can convert the request to an array of MultiPartFile
.
You can also replace HttpServletRequest
with MultipartHttpServletRequest
, which gives you access to the headers of the individual parts.
Solution 2
You can simply use a controller method like this:
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<?> uploadFile(
@RequestParam("file") MultipartFile file) {
try {
// Handle the received file here
// ...
}
catch (Exception e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(HttpStatus.OK);
} // method uploadFile
Without any additional configurations for Spring Boot.
Using the following html form client side:
<html>
<body>
<form action="/uploadFile" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
</body>
</html>
If you want to set limits on files size you can do it in the application.properties
:
# File size limit
multipart.maxFileSize = 3Mb
# Total request size for a multipart/form-data
multipart.maxRequestSize = 20Mb
Moreover to send the file with Ajax take a look here: http://blog.netgloo.com/2015/02/08/spring-boot-file-upload-with-ajax/
Solution 3
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("5120MB");
factory.setMaxRequestSize("5120MB");
return factory.createMultipartConfig();
}
put it in class where you are defining beans
Solution 4
Add @RequestPart
instead of @RequestParam
public UploadFile upload(@RequestPart(name = "file") MultipartFile multipartFile{
//your code to process filee
}
Solution 5
In Controller, your method should be;
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<SaveResponse> uploadAttachment(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
....
Further, you need to update application.yml (or application.properties) to support maximum file size and request size.
spring:
http:
multipart:
max-file-size: 5MB
max-request-size: 20MB
Rob McFeely
Lead Software Developer, Electronic and Computer Engineer, Image Processing PhD
Updated on July 13, 2021Comments
-
Rob McFeely almost 3 years
Im using Spring Boot and want to use a Controller to receive a multipart file upload. When sending the file I keep getting the error 415 unsupported content type response and the controller is never reached
There was an unexpected error (type=Unsupported Media Type, status=415). Content type 'multipart/form-data;boundary=----WebKitFormBoundary1KvzQ1rt2V1BBbb8' not supported
Ive tried sending using form:action in html/jsp page and also in a standalone client application which uses RestTemplate. All attempts give the same result
multipart/form-data;boundary=XXXXX not supported.
It seems from multipart documentation that the boundary param has to be added to the multipart upload however this seems to not match the controller receiving
"multipart/form-data"
My controller method is setup as follows
@RequestMapping(value = "/things", method = RequestMethod.POST, consumes = "multipart/form-data" , produces = { "application/json", "application/xml" }) public ResponseEntity<ThingRepresentation> submitThing(HttpServletRequest request, @PathVariable("domain") String domainParam, @RequestParam(value = "type") String thingTypeParam, @RequestBody MultipartFile[] submissions) throws Exception
With Bean Setup
@Bean public MultipartConfigElement multipartConfigElement() { return new MultipartConfigElement(""); } @Bean public MultipartResolver multipartResolver() { org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver(); multipartResolver.setMaxUploadSize(1000000); return multipartResolver; }
As you can see I've set the consumes type to "multipart/form-data" but when the multipart is sent it must have a boundary parameter and places a random boundary string.
Can anyone please tell me how I can either set the content type in controller to match or change my request to match my controller setup?
My attempts to send ... Attempt 1...
<html lang="en"> <body> <br> <h2>Upload New File to this Bucket</h2> <form action="http://localhost:8280/appname/domains/abc/things?type=abcdef00-1111-4b38-8026-315b13dc8706" method="post" enctype="multipart/form-data"> <table width="60%" border="1" cellspacing="0"> <tr> <td width="35%"><strong>File to upload</strong></td> <td width="65%"><input type="file" name="file" /></td> </tr> <tr> <td> </td> <td><input type="submit" name="submit" value="Add" /></td> </tr> </table> </form> </body> </html>
Attempt 2....
RestTemplate template = new RestTemplate(); MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>(); parts.add("file", new FileSystemResource(pathToFile)); try{ URI response = template.postForLocation(url, parts); }catch(HttpClientErrorException e){ System.out.println(e.getResponseBodyAsString()); }
Attempt 3...
FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); formHttpMessageConverter.setCharset(Charset.forName("UTF8")); RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add( formHttpMessageConverter ); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>(); map.add("file", new FileSystemResource(path)); HttpHeaders imageHeaders = new HttpHeaders(); imageHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity<MultiValueMap<String, Object>> imageEntity = new HttpEntity<MultiValueMap<String, Object>>(map, imageHeaders); ResponseEntity e= restTemplate.exchange(uri, HttpMethod.POST, imageEntity, Boolean.class); System.out.println(e.toString());
-
Rob McFeely over 9 yearsThat worked thanks. All my client attempts now work against this fix on the server side. Turns out that I didn't require the MultipartConfigElement and the MultipartResolver beans. Possibly boot is creating these for me.
-
mal over 2 yearsI cannot upvote this enough.