Java – Multipart File upload Spring Boot

javamultipartspringspring-bootspring-mvc

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>&nbsp;</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());

Best Answer

@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.

Related Topic