Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multipart File upload Spring Boot

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()); 
like image 889
Rob McFeely Avatar asked Sep 06 '14 11:09

Rob McFeely


People also ask

How do I upload files to spring boot?

Spring Boot file uploader Create a Spring @Controller class; Add a method to the controller class which takes Spring's MultipartFile as an argument; Save the uploaded file to a directory on the server; and. Send a response code to the client indicating the Spring file upload was successful.

What is multipart file in spring boot?

public interface MultipartFile extends InputStreamSource. A representation of an uploaded file received in a multipart request. The file contents are either stored in memory or temporarily on disk. In either case, the user is responsible for copying file contents to a session-level or persistent store as and if desired ...

What is a multipart file upload?

Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.

How do you send a multipart file in RestTemplate in spring boot?

We need to create HttpEntitywith header and body. Set the content-type header value to MediaType. MULTIPART_FORM_DATA. When this header is set, RestTemplate automatically marshals the file data along with some metadata.


2 Answers

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

like image 59
a better oliver Avatar answered Sep 27 '22 18:09

a better oliver


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/

like image 45
Andrea Avatar answered Sep 27 '22 18:09

Andrea