CeePlusPlus
CeePlusPlus

Reputation: 841

Making a MultiPart Put request via Spring Rest to call a API with formData (Replace Apache MultipartEntityBuilder with REST)

I have a PUT API to call to send my data that expects a Multipart Request. (Swagger has the API listed as Paramter Type formData; Data Type file).

I have this code working fine via Apache's Http Library, but to match the rest of the program I would like to use Spring Rest Template to make the same call.

//Via Apache:
Uri uri = "http://putmyresults.com";
ResultObject results = buildResultObject(myData);
MultipartEntityBuilder meb = MultipartEntityBuilder.create();
meb.addBinaryBody("file", results.convertToBytes(), ContentType.create("application/octet-stream"),"MyResultFile");
HttpEntity entity = meb.build();
put.setEntity(entity);

put.setHeader(new BasicHeader("Authorization","myToken"));
put.setHeader("Accept","application/json,application,octet-stream");
getMyCloseableHttpClient().execute(put);
//process response codes...



//Sample working REST for GET request:
Uri uri = "http://getmyresults.com/section5/resultId?sectionId=foo";
RestTemplate rest = new RestTemplate;

org.springframework.http.HttpEntity header = new HttpHeaders();
header.set("Authorization","myToken");
header.setContentType(MediaType.APPLICATION_JSON);
header.setAccept(Arrays.asList(MediaType.APPLICATION_JSON,MediaType.APPLICATION_OCTET_STREAM));

HttpEntity<String> entity = new HttpEntity("parameters", headers);
rest.exchange(uri, HttpMethod.GET, entity, Resource.class);
//process response...

But I can't seem to make the PUT request via REST. This is what I have so far:

Uri uri = "http://putmyresults.com";
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
ResultObject results = buildResultObject(myData);
byte[] bytes = results.convertToBytes();

HttpHeaders header = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
org.springframework.http.HttpEntity<byte[]> entity = new HttpEntity<>(bytes,headers);
map.add("MyResultFile",entity);

HttpHeaders tokenHeader = new HttpHeaders();
tokenHeader.set(new BasicHeader("Authorization","myToken"));
tokenHeader.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> tokenEntity = new HttpEntity("parameters", headers);
map.add("parameters",tokenEntity);

org.springframework.http.HttpEntity<<MultiValueMap<String,Object> requestMap = new org.springframework.http.HttpEntity<>(map);
new RestTemplate().exchange(uri,HttpMethod.PUT,requestMap,String.class);

Server Header:

@PutMapping(path = "/xyz")
public ResponseEntity putRequest{
    HttpServletRequest request,
    HttpServletResponse response,
    @PathVariable String id,
    @RequestParam("file") MultipartFile uploadedFile,
    @RequestParam String sample,
    @RequestParam String sample2 throws Exception  {
        uploadedFile.getBytes(); ...
    }
}

Thanks for your help.

Upvotes: 2

Views: 1803

Answers (3)

CeePlusPlus
CeePlusPlus

Reputation: 841

With the help of @user2683814 and this article, this is what works for me:

import org.springframework.http.*; //Used with 5.1.9.RELEASE

Uri uri = "http://putmyresults.com";
byte[] bytes = results.convertToBytes();

MultiValueMap<String,String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition cd = ContentDisposition.builder("form-data").
name("file").filename("myFile").build();
filemap.add(HttpHeaders.CONTENT_DISPOSITION,cd.toString());

HttpEntity<byte[]> fileEntity = new HttpEntity<>(bytes,fileMap);
MultiValueMap<String,Object> body = new LinkedMultiValueMap<>();
body.add("file",fileEntity);


HttpHeaders tokenHeader = new HttpHeaders();
tokenHeader.set("Authorization","myToken");
tokenHeader.setContentType(MediaType.MULITPART_FORM_DATA);

HttpEntity<MultiValueMap<String,Object>> requestMap = new HttpEntity<>(body,securedTokenHeaders);


new RestTemplate().exchange(uri,HttpMethod.PUT,requestMap,String.class)

Upvotes: 0

s7vr
s7vr

Reputation: 75914

You need to add the content type as multipart along with content disposition. Make sure to import spring classes as there are same classes in Apache Http library.

String uri = "http://putmyresults.com";
MultiValueMap<String,Object> multipartRequest = new LinkedMultiValueMap<>();

ResultObject results = buildResultObject(myData);
byte[] bytes = results.convertToAvroBytes()
HttpHeaders fileHeader = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("file","mydata");
HttpEntity<byte[]> entity = new HttpEntity<>(bytes,fileHeader);
multipartRequest.add("file",entity);

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

HttpEntity<MultiValueMap<String,Object>> requestMap = new HttpEntity<>(multipartRequest,header);
String response = new RestTemplate().exchange(uri,HttpMethod.PUT,requestMap,String.class);

Reference:multipart-file-upload-using-spring-rest-template-spring-web-mvc

Upvotes: 2

bRiJeSh
bRiJeSh

Reputation: 810

Try this:

MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();

// creating an HttpEntity for the binary part
HttpHeaders header = new HttpHeaders();
pictureHeader.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<ByteArrayResource> file = new HttpEntity<>(pngPicture, pictureHeader);
multipartRequest.add("file", file);

HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<> 
(multipartRequest, header);
ResultObject result = restTemplate.put(UPLOAD_URL, requestEntity);

Upvotes: 3

Related Questions