Multipart File Upload Using Spring Rest Template + Spring Web MVC Multipart File Upload Using Spring Rest Template + Spring Web MVC spring spring

Multipart File Upload Using Spring Rest Template + Spring Web MVC


The Multipart File Upload worked after following code modification to Upload using RestTemplate

LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();map.add("file", new ClassPathResource(file));HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.MULTIPART_FORM_DATA);HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new    HttpEntity<LinkedMultiValueMap<String, Object>>(                    map, headers);ResponseEntity<String> result = template.get().exchange(                    contextPath.get() + path, HttpMethod.POST, requestEntity,                    String.class);

And adding MultipartFilter to web.xml

    <filter>        <filter-name>multipartFilter</filter-name>        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>multipartFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>


For most use cases, it's not correct to register MultipartFilter in web.xml because Spring MVC already does the work of processing your multipart request. It's even written in the filter's javadoc.

On the server side, define a multipartResolver bean in your app context:

@Beanpublic CommonsMultipartResolver multipartResolver(){    CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();    commonsMultipartResolver.setDefaultEncoding("utf-8");    commonsMultipartResolver.setMaxUploadSize(50000000);    return commonsMultipartResolver;}

On the client side, here's how to prepare the request for use with Spring RestTemplate API:

    HttpHeaders headers = new HttpHeaders();    headers.setContentType(MediaType.MULTIPART_FORM_DATA);    LinkedMultiValueMap<String, String> pdfHeaderMap = new LinkedMultiValueMap<>();    pdfHeaderMap.add("Content-disposition", "form-data; name=filex; filename=" + file.getOriginalFilename());    pdfHeaderMap.add("Content-type", "application/pdf");    HttpEntity<byte[]> doc = new HttpEntity<byte[]>(file.getBytes(), pdfHeaderMap);    LinkedMultiValueMap<String, Object> multipartReqMap = new LinkedMultiValueMap<>();    multipartReqMap.add("filex", doc);    HttpEntity<LinkedMultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multipartReqMap, headers);    ResponseEntity<MyResponse> resE = restTemplate.exchange(uri, HttpMethod.POST, reqEntity, MyResponse.class);

The important thing is really to provide a Content-disposition header using the exact case, and adding name and filename specifiers, otherwise your part will be discarded by the multipart resolver.

Then, your controller method can handle the uploaded file with the following argument:

@RequestParam("filex") MultipartFile file

Hope this helps.


Here are my working example

@RequestMapping(value = "/api/v1/files/upload", method =RequestMethod.POST)public ResponseEntity<?> upload(@RequestParam("files") MultipartFile[] files) {    LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();    List<String> tempFileNames = new ArrayList<>();    String tempFileName;    FileOutputStream fo;    try {        for (MultipartFile file : files) {            tempFileName = "/tmp/" + file.getOriginalFilename();            tempFileNames.add(tempFileName);            fo = new FileOutputStream(tempFileName);            fo.write(file.getBytes());            fo.close();            map.add("files", new FileSystemResource(tempFileName));        }        HttpHeaders headers = new HttpHeaders();        headers.setContentType(MediaType.MULTIPART_FORM_DATA);        HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);        String response = restTemplate.postForObject(uploadFilesUrl, requestEntity, String.class);    } catch (IOException e) {        e.printStackTrace();    }    for (String fileName : tempFileNames) {        File f = new File(fileName);        f.delete();    }    return new ResponseEntity<Object>(HttpStatus.OK);}