Reputation: 157
Can we send MultipartFile inside a Custom Request Object in a Rest Template call? Similarly, can we receive a MutlipartFile inside a Custom Response Object returned from a Rest call made through the Rest Template?
Basically, we need to send other essential attributes along with a File Upload and receive few attributes along with a File Download.
Is this possible through a Spring Rest Template?
Below is the Code,
public class UploadRequest {
private Long checkSum;
private MultiPartFile fileContents;
//setters and getters
}
We receive the MultipartFile from a controller end point, we just relay it to another endpoint using the below is the Rest template call,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("uploadRequest", uploadRequest);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
it results in the below exception,
com.fasterxml.jackson.databind.exc.InvalidDefinitionException No Serializer for class java.io.FileDescriptor
and
no properties discovered to create BeanSerializer
Upvotes: 0
Views: 3409
Reputation: 157
We made the following changes to finally get it working,
We changed the RestController endpoints attribute annotations, we had the @RequestBody
annotation for the attribute UploadRequest
, we had to change it to @ModelAttribute
as per the suggestions in content-type-multipart-form-databoundary-charset-utf-8-not-supported This helped us overcome the Http Error 415 - UnsupportedMediaType.
On the Client Side, we introduce the class FileSystemResource
as per the suggestions in Rest Api Call over Rest Template with MultipartFile
public static class FileSystemResource extends ByteArrayResource {
private String fileName;
public FileSystemResource(byte[] byteArray , String filename) {
super(byteArray);
this.fileName = filename;
}
public String getFilename() { return fileName; }
public void setFilename(String fileName) { this.fileName= fileName; }
}
then changed the rest call as below,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
MultiValueMap<String, Object> map = new MultiValueMap<>();
map.add("checkSum", request.getCheckSum());
map.add("fileContents", new FileSystemResource(request.getFile().getBytes(), request.getFile().getOriginalFileName()));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
after these changes, it worked.
Upvotes: 0
Reputation: 868
Yes, you can. Spring has a class that handles Multipart files - org.springframework.web.multipart.MultipartFile
. You can use it to send or receive multipart files. But the request body needs to be form-data
. You can not send file over x-www-form-urlencoded
.
Just use MultipartFile
as an attribure in your custom request and you sould be good to go.
@Component
public class CustomRequest {
...
private Long checkSum;
private MultipartFile file;
...
// make sure you have the getters and setters right
// also the filed names are spelled exactly the same as they are in the form
// for example myFile and my_file are different
public MultiValueMap<String, String> getRequestBody() {
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<String, String>();
requestBody.add("checkSum", this.getCheckSum());
requestBody.add("fileContents", this.getFileContents());
// add other fileds if you need
return requestBody;
}
}
In the controller,
HttpHeaders headers = new HttpHeaders();
headers.setContentType("mutipart/form-data");
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(customRequest.getRequestBody(), headers);
ResponseEntity<UploadResponse> responseEntity = restTemplate.postForEntity(uploadUrl, requestEntity, UploadResponse.class);
What happened was that you were sending the request body inside the MultiValueMap
. You have to send the form data inside the MultiValueMap
. And make sure your response has the getters and setters. Spring needs getter setter to serialize the object.
Documentation is here
Upvotes: 1