Multipart File Upload Using Spring Rest Template + Spring Web MVC

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>

How to send Multipart form data with restTemplate Spring-mvc

Reading the whole file in a ByteArrayResource can be a memory consumption issue with large files.

You can proxy a file upload in a spring mvc controller using a InputStreamResource:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<?> uploadImages(@RequestPart("images") final MultipartFile[] files) throws IOException {
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
String response;
HttpStatus httpStatus = HttpStatus.CREATED;

try {
for (MultipartFile file : files) {
if (!file.isEmpty()) {
map.add("images", new MultipartInputStreamFileResource(file.getInputStream(), file.getOriginalFilename()));
}
}

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);

String url = "http://example.com/upload";

HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
response = restTemplate.postForObject(url, requestEntity, String.class);

} catch (HttpStatusCodeException e) {
httpStatus = HttpStatus.valueOf(e.getStatusCode().value());
response = e.getResponseBodyAsString();
} catch (Exception e) {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
response = e.getMessage();
}

return new ResponseEntity<>(response, httpStatus);
}

class MultipartInputStreamFileResource extends InputStreamResource {

private final String filename;

MultipartInputStreamFileResource(InputStream inputStream, String filename) {
super(inputStream);
this.filename = filename;
}

@Override
public String getFilename() {
return this.filename;
}

@Override
public long contentLength() throws IOException {
return -1; // we do not want to generally read the whole stream into memory ...
}
}

How do I send a multipartFile using spring RestTemplate?

The solution turned out to be very simple, as usual. Simply call getResource() on the multipartFile.

public void loadInvoices(MultipartFile invoices) throws IOException {

Resource invoicesResource = invoices.getResource();

LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("file", invoicesResource);

HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);

restTemplate.postForEntity("my/url", httpEntity, SommeClass.class);
}

Uploading a List of MultipartFile with Spring 4 restTemplate (Java Client & RestController)

It looks like the request payload that you are sending from FileUploadClient does not match what's server is expecting. Could you try changing the following:

MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
for(MultipartFile file : multiPartFileList) {
map.add(file.getName(), new ByteArrayResource(file.getBytes()));
}

to

MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
List<ByteArrayResource> files = new ArrayList<>();
for(MultipartFile file : multiPartFileList) {
files.add(new ByteArrayResource(file.getBytes()));
}
map.put("files", files);

Also, could you try changing the server's method signature to the following:

public ResponseEntity<?> uploadFiles(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request) {

Update

While uploading multiple files, you need to make sure getFileName of ByteArrayResource returns same value every time. If not, you will always get an empty array.

E.g. the following works for me:

Client:

MultiValueMap<String, Object> data = new LinkedMultiValueMap<String, Object>(); 
for(MultipartFile file : multiPartFileList) {
ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {
@Override
public String getFilename() {
return "";
}
};
data.add("files", resource);
}

Server

public ResponseEntity<?> upload(@RequestParam("files") MultipartFile[] files){


Related Topics



Leave a reply



Submit