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
How to Add Unicode in Truetype0Font on PDFbox 2.0.0
Package Conflicts with Automatic Modules in Java 9
How to Keep a Scanner from Throwing Exceptions When the Wrong Type Is Entered
Java 1.6: Creating an Array of List<T>
Docker: Combine Multiple Images
How to Find a Whole Word in a String in Java
Java.Lang.Illegalaccesserror: Tried to Access Method
Converting Integer to String with Comma for Thousands
When Should I Use an Interface in Java
What Is the --Release Flag in the Java 9 Compiler
Where Do Java and .Net String Literals Reside
How to Get Information About the Local Variables Using Java Reflection
Jfreechart Line Chart with Text at Each Point
Java 8: Difference Between Method Reference Bound Receiver and Unbound Receiver