Multipart File upload Spring Boot

134,987

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
Share:
134,987
Rob McFeely
Author by

Rob McFeely

Lead Software Developer, Electronic and Computer Engineer, Image Processing PhD

Updated on July 13, 2021

Comments

  • Rob McFeely
    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>&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());
    
  • Rob McFeely
    Rob McFeely over 9 years
    That 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
    mal over 2 years
    I cannot upvote this enough.