Spring REST Template for Byte - java

I am fetching the byte array using spring framework rest template,
But I also need to fetch the Mediatype of this byte .
The mediaType of this bytearray can be of any type.
The code used now for fetching byte is below.
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.valueOf("application/pdf")));
ResponseEntity<byte[]> result = restTemp.exchange(url, HttpMethod.GET, entity, byte[].class,documentId);
The above code will fetch only pdf content type.
How to set the contentType to accept any generic MediaType because the service at the other end is providing any random MediaType for the byteArray.
Could someone please suggest how the MediaType can be fetched.
Any suggestions are welcome..

Just not send the accept header to not force the server to return that content-type. This is the same as sending a wildcard */*
//HttpHeaders headers = new HttpHeaders();
//headers.setAccept(Collections.singletonList(MediaType.WILDCARD));
ResponseEntity<byte[]> result = restTemp.exchange(url, HttpMethod.GET, entity, byte[].class,documentId);
After this, extract the content-type from the headers of the response
byte body[] = result.getBody();
MediaType contentType = result.getHeaders().getContentType();

You can set the MediaType as application/octet-stream , look at here

You can store a media type in the HTTP headers and use - ResponseEntity.getHeaders(), for instance. or you can wrap byte array and media type into holder class.

MediaType mediaType = result.getHeaders().getContentType();

Related

springboot RestTemplate call url and https response headers(content-type:audio/wav) ,how to save as *.wav file?

I use spring RestTemplate to call the the Third-party services,
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
result like this:
forEntity
status:200
headers:
content-type=audio/wav
body:"RIFFä,,,xxxxxxx......"
response is enter image description here
the body seems to wav data, I want to save the data to wav file.
if I Go directly to the link in chrome, it's ok to play, and download.
Use RestTemplate.execute instead, which allows you to attach a ResponseExtractor, in which you have access to the response body which an InputStream, we take that InputStream and write it to a file
restTemplate.execute(
url,
HttpMethod.GET,
request -> {},
response -> {
//get response body as inputstream
InputStream in = response.getBody();
//write inputstream to a local file
Files.copy(in, Paths.get("C:/path/to/file.wav"), StandardCopyOption.REPLACE_EXISTING);
return null;
}
);
In Java a String is not the same as a byte[] array.
Therefore treating audio-content (which is binary data)
as a string (i.e. text data) is begging for problems.
Instead, you should get the response body as byte[].
Then you can save the bytes to a file.
For example like this:
ResponseEntity<byte[]> entity = restTemplate.getForEntity(url, byte[].class);
byte[] body = entity.getBody();
Path path = Paths.get("example.wav");
Files.write(path, body);

415 error while calling post API from jersey client

I have below API which returns back the access_token.
POST https://idcs-xxxxxxxxxbf08128c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token
in header content-type is application/x-www-form-urlencoded. also in body it contains below parameter.
I send user name and password and it is secured with basic authentication. It provides access_token when I call from postman. also it provides output when I consume using HttpUrlConnection
url = new URL(tokenURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Authorization", auth);
connection.setRequestProperty("Accept", "application/json");
OutputStream os = connection.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("grant_type=client_credentials&scope=" + scope);
The above code is working properly. But when I use jersey it gives 415 error. I am using below code.
String user="idcs-oda-zzzxxxxxf93560b94eb8a2e2a4c9aac9a3ff-t0_APPID";
String password="xxxxxxx-6f71-4af2-b5cc-9110890d1456";
String scope = "https://idcs-oda-xxxxxxxxxxxxxxxxe2a4c9aac9a3ff-t0.data.digitalassistant.oci.oc-test.com/api/v1";
String tokenURL = "https://idcs-xxxxxxxxxxxxxxxx28c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token";
HttpAuthenticationFeature feature= HttpAuthenticationFeature
.basicBuilder()
.nonPreemptive()
.credentials(user,password)
.build();
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(feature);
Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget= client.target(tokenURL);
PostDetails post= new PostDetails("client_credentials",scope); //Bean class to assign body parameter
Response response= webTarget.request()
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
System.out.println(response);
Can somebody tell me what mistake I am doing in Response line.
You need to set your Accept on the request method:
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
You also need to ensure that if your API accepts application/x-www-form-urlencoded content, that is what you are sending.
Currently, you are sending application/json content based on your usage of Entity.json(post).
I don't know what type is assigned to post, but you need to figure out how to convert it either to a Form or a MultiValuedMap<String,String>, and then use the form method on Entity to submit your content.
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.form(postForm)); //assuming postForm typed as Form or MultiValuedMap<String,String>
Taking a guess regarding post, creating postForm as a MultiValuedMap<String,String> may be as simple as the following (which you would place prior to your request, of course).
MultiValuedMap<String,String> postForm = new MultiValuedHashMap<>();
postForm.add("client_credentials",scope);
What you need is:
Response response= webTarget.request()
.accept("application/json") // Accept field from header of request
.header("Content-Type", "application/x-www-form-urlencoded") //manually set content-tyoe
.post(Entity.entity(input, MediaType.TEXT_PLAIN)); // request body
The best way to see what is Jersey actually is sending is to register logger, and log network. For example:
clientConfig.register(
new LoggingFeature(
new Slf4jLogger(this.getClass().getName(), null)));
where Slf4jLogger is from org.apache.cxf:cxf-core.

In the postman I am getting proper json response but when I hit the service through restTemplate I am getting chinese characters

Code:
RestTemplate template=new RestTemplate();
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity=new HttpEntity<>(body,headers);
ResponseEntity<String> postForEntity = template.postForEntity("url", httpEntity, String.class);
Json Response:
笀∀琀爀愀渀猀愀挀琀椀漀渀䤀䐀∀㨀∀㄀娀㜀㌀㐀䔀㤀㈀㈀㘀㜀㈀㌀㔀㠀㘀㤀㔀∀Ⰰ∀猀琀愀琀甀猀∀㨀 Ⰰ∀爀攀焀吀猀∀㨀∀㈀ ㈀ ⴀ 㐀ⴀ㈀ ∀Ⰰ∀愀搀搀爀倀漀椀渀琀䰀椀猀琀∀㨀嬀笀∀爀攀焀䤀搀∀㨀∀㄀娀㜀㌀㐀䔀㤀㈀㈀㘀㜀㈀㌀㔀㠀㘀㤀㔀∀Ⰰ∀爀攀猀椀䌀漀洀∀㨀∀唀∀Ⰰ∀愀搀搀爀倀渀琀吀欀渀∀㨀∀∀紀崀紀
by using this for loop I am able to get the correct json response:
for(int i=0; i< response.length(); i++) {
encoded += ((char) ((int)response.charAt(i) / 256 ));
}
Postman headers:
Request Headers:
Accept:Application/Json
Content-type:Application/Json
Response Headers:
Content-Type →application/json; charset=utf-8
Date →Thu, 04 Jun 2020 15:41:49 GMT
Server →Server Name
Transfer-Encoding →chunked
But I want to get the response without using this for loop.
In your code you are trying to receive the response in String format and here is the issue. First receive the response as Object, Once you receive the response as Object then try to convert it in String.
RestTemplate template=new RestTemplate();
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity=new HttpEntity<>(body,headers);
ResponseEntity<Object> postForEntity = template.postForEntity("url", httpEntity, Object.class);
Maybe you need to pass "Accept-Language" header.
It could be possible that postman sends default header value as "en-US"
The problem is the encoding. when sending your request make sure that you add the header
Content-type:Application/Json; charset=utf-8
And not just
Content-type:Application/Json

How to upload file with Okhttp3 (REST API)

I'm trying to upload an image with uploading bytes of Google Photos API .
So here is my request with OkHttp3:
Request request = new Request.Builder()
.addHeader("Authorization", "Bearer " + token)
.addHeader("Content-type:", "application/octet-stream")
.addHeader("X-Goog-Upload-Content-Type:",mimeType)
.addHeader("X-Goog-Upload-Protocol:", "raw")
.url("https://photoslibrary.googleapis.com/v1/uploads")
.post(requestBody) // how to build request body?
.build();
the documentation says: "In the request body, include the binary of the file:"
media-binary-data
What does it means?
For a given file, I assume that it is:
byte[] data = FileUtils.readFileToByteArray(new File(myPath));
But how do you build this requestBody with data array?
EDIT
I already tried :
MediaType mType = MediaType.parse("application/octet-stream; charset=utf-8");
RequestBody requestBody = RequestBody.create(mType,new File(path));
Exception :
okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
Thank you in advance for putting me on the track!
RequestBody has a few overloaded factory methods:
create(MediaType, byte[])
create(MediaType, File)
It looks like you're supplying the second parameter in either case correctly.
As for the MediaType parameter, I usually use the MIME type of the underlying image rather than specifying general binary content, e.g.:
MediaType.parse("image/jpeg")
or
MediaType.parse("image/png")
...
unfortunately I left the ":" after the parameter keys !!!!
Request request = new Request.Builder()
.addHeader("Authorization", "Bearer " + token)
.addHeader("Content-type", "application/octet-stream")// and no X-Goog-Upload-Content-Type :
.addHeader("X-Goog-Upload-Content-Type",mimeType)//same
.addHeader("X-Goog-Upload-Protocol", "raw")//same
.url("https://photoslibrary.googleapis.com/v1/uploads")
.post(requestBody)
.build();
And for the requestBody:
byte [] data = FileUtils.readFileToByteArray(file);
RequestBody requestBody = RequestBody.create(mimeTypeOfFile,data);

How to receive application/pdf response from a server using RestTemplate

I am trying capture the response of an HTTP request made by my java client code. The response has a content-type of application/pdf. In the logs I can see that the server sent a response in
Object result = getRestTemplate().postForObject(urlString, formDataHttpEntity, returnClassObject, parametersMapStringString);
and I get the following JUnit error:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type
[java.lang.Object] and content type [application/pdf]
What do I need to do to get past this? My ultimate goal is to take this in a byte[] and push it in a DB table field of blob type
Note: I get the following response header from the server
HTTP/1.1 200 OK Cache-Control: max-age=0,must-revalidate
Content-Disposition: attachment; filename="Executive Summary.PDF"
Content-Type: application/pdf
Thanks Thomas it worked.
I added ByteArrayHttpMessageConverter to the RestTemplate and it worked.
Code I added:
ByteArrayHttpMessageConverter byteArrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
List<MediaType> supportedApplicationTypes = new ArrayList<>();
MediaType pdfApplication = new MediaType("application","pdf");
supportedApplicationTypes.add(pdfApplication);
byteArrayHttpMessageConverter.setSupportedMediaTypes(supportedApplicationTypes);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(byteArrayHttpMessageConverter);
restTemplate = new RestTemplate();
restTemplate.setMessageConverters(messageConverters);
Object result = getRestTemplate().getForObject(url, returnClass, parameters);
byte[] resultByteArr = (byte[])result;
API I calling to get PDF is returning InputStreamResource.
To get the response, I used it this way and I was able to get a successful byte array of pdf.
public byte[] callApiToGetPDF(Object reqData) {
String urlForEndPoint= baseUrl + "/" + "";
HttpEntity<Object> entity = new HttpEntity<>(reqData, buildHeaders());
return restTemplate.postForEntity(urlForEndPoint, entity, byte[].class).getBody();
}

Categories

Resources