I'm writing a Java Application, which posts content to a wordpress Rest Api. However I have a problem with programmatically POST a ".png" file with Java SpringBoot, because I don't know how to add the form-data body to HttpEntity<>(body, headers);
I've accomplished this using Postman -> Body -> form-data ->"file":"myFile.png" see screenshots: headers in Postman here Body in Postman here
I've written this code in Java Spring:
private MediaResponse uploadMedia (File graphicsFile) {
String uploadUrl = baseUrl + mediaUrl;
HttpHeaders headers = getHttpHeader();
headers.add(headerKeyAuthorization, User.getInstance().getUsertoken());
headers.add("Content-Disposition", "attachment;filename=image.png");
headers.add("Content-Type", "image/png");
...
I thought about doing something like that:
Map<String, File> body = new HashMap<>();
parameters.put("file", new File("image.png"));
HttpEntity requestEntity = new HttpEntity<>(body, headers);
//not interesting in this case
//excecuteMediaRequest(uploadUrl, HttpMethod.POST, requestEntity);
to add the file to the body.
Now my question is: which "key":"value" pairs I have to set in the header(HttpHeaders), and how can I add the file to the body to achieve the same POST like in Postman?
My actual solution of course produces an error:
Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [image/png]
Solution:
I've get it to work with a little workaround and @Ajit Somans help. Here is the code that works for my scenario. Note that the methods generateBytArray(), executeMediaRequest() and the class MediaResponse are self written.
/**
* Uploads media to a rest resource.
*
* @param graphicsFile the media file which should be uploaded
* @return a MediaResponse which has access to resource urls and media information.
*/
private MediaResponse uploadMedia (File graphicsFile) {
String uploadUrl = baseUrl + mediaUrl;
final String filename = graphicsFile.getName();
//create headers for form data
HttpHeaders header = getHttpHeader();
header.set(headerKeyAuthorization, User.getInstance().getUsertoken());
header.set("Content-Disposition", "form-data;");
//produces a byte array resource
ByteArrayResource contentAsResource = new ByteArrayResource(generateBytArray(graphicsFile)){
@Override
public String getFilename(){
return filename;
}
};
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
formData.add("file", contentAsResource);
//create request entity with header and body
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, header);
//executes request with in custom method.
MediaResponse respondingObject = executeMediaRequest(uploadUrl, HttpMethod.POST, requestEntity);
return respondingObject;
}
As you can see, we don't set the "Content-Type" option, but set the "Content-Disposition" to "form-data" instead of "attachment". The Key Part is to convert the media File, which is .png, into a byte[]. After that we produce a ByteArrayResource like mentioned in this post. At least we're just setting the byte array into the body and execute the request to the given url endpoint.
here the method to convert a File into a byte[]:
/**
* generates a byte Array of a file.
*
* @param file the file to generate a byte array of.
* @return byte array of the given file.
*/
private byte[] generateBytArray(File file) {
byte[] res = new byte[0];
try {
//File file = fileResource.getFile();
BufferedImage image = ImageIO.read(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
res = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return res;
}
And the excecuting method:
/**
* Method to execute a Request to a Rest Api where we want to upload media to.
*
* @param url the url endpoint of the resource, where we upload the media file.
* @param method the http request method, which ist POST in this case.
* @param entity the http entity where header and body are stored.
* @return a MediaResponse which has access to resource urls and media information.
*/
private MediaResponse executeMediaRequest(String url, HttpMethod method, HttpEntity entity) {
ParameterizedTypeReference<MediaResponse> responseType = new ParameterizedTypeReference<MediaResponse>() {};
ResponseEntity<MediaResponse> response = template.exchange(url, method, entity,
responseType, MediaResponse.class);
MediaResponse responseObject = response.getBody();
logger.info("\n ******** POST MEDIA from response with param: \n " +
"Post id: '{}' \n " +
"Post REST resource endpoint: '{}' \n" +
"Post Permalink '{}'\n *********",
responseObject.getMediaID(), responseObject.getRestSelfUrl(), responseObject.getPermalink());
return responseObject;
}
Thanks @Ajit Soman