How to upload file with Okhttp3 (REST API) - java

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);

Related

Not authorized to access scope - Amazon Advertising API

My purpose is to download the advertising report using existing application details such as AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & Access tokens to other java application.
I was able to get the new access token using AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & refresh_token. Below is the code to fetch a new access token.
OkHttpClient client = new OkHttpClient();
Response response;
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=refresh_token&refresh_token=" + refreshToken + "&client_id=" + amzClientId + "&client_secret=" + amzClientSceret);
Request request = new Request.Builder()
.url(“https://api.amazon.com/auth/o2/token”)
.post(body)
.addHeader("content-type", "application/x-www-form-urlencoded")
.build();
response = client.newCall(request).execute();
After sending the api request to fetch the campaign level stats data, is gives the following error
{"code":"UNAUTHORIZED","
details":"Not authorized to access scope XXXXXXXXXXXXXXXXXX","
requestId":"xxxxxxxxxxxxx"}"
My question here is, Can I use the same existing AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & Access tokens to fetch stats to different java applications(without using login with amazon)?
Any help would be appreciated. Thank you!!
You need to include the access token and client ID for subsequent requests.
.addHeader("Authorization", "Bearer " + access_token)
.addHeader("Amazon-Advertising-API-ClientId", client_id)

How to add parameter in request URL( Java 11)?

I'm absolute beginner in java. Trying to send some http request using the built in java httpclient.
How can I add the request parameters into the URI in such format:
parameter = hi
url = "https://www.url.com?parameter=hi"
With the code, I'm using, I can only set the headers but not the request parameters
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create(url))
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
Thank you very much!
With native Java 11, it has to be done like you did. You need to add the parameters within the url parameter already. Or you need to create your own builder that allows you to append parameter.
However, your requested behaviour is possible if you make use of libraries. One way to do it is to make use of Apache URIBuilder
var client = HttpClient.newHttpClient();
URI uri = new URIBuilder(httpGet.getURI())
.addParameter("parameter", "hi")
.build();
var request = HttpRequest.newBuilder(uri)
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
You don't have methods for adding parameters, but you can use String.format() to format the URL nicely.
final static String URL_FORMAT = "http://url.com?%s=%s";
final String request = String.format(URL_FORMAT, "paramater", "hi");

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.

How to send a POST with form-data in Body in RestAssured setting multipart with a specific content-type

Trying to send a POST request with form-data in Body in RestAssured, however not sure how should do it.
In Postman, it's fine.
I've tried things like:
public Response create() {
return super
.given()
.contentType("multipart/form-data")
.multiPart("MetaDataOne", new File("file.txt"))
.multiPart("MetaDataTwo", new File("file2.txt"))
.basePath("/create")
.log().all()
.post()
.then()
.log().all()
.extract()
.response();
}
But seems that my files are not being sent in the request.
Console log
Multiparts
Content-Disposition form-data; name = MetadataOne; filename = file
Content-Type: application/octet-stream
{"error": 415, "description": Content type application/octet-stream not supported}
Headers
Can you try with this, This should overwrite the Content-Type as multipart/form-data rather than application/octet-stream
given().contentType("multipart/form-data").multiPart("MetaDataOne", new File("file.txt"), "multipart/form-data")
.multiPart("MetaDataTwo", new File("file2.txt"), "multipart/form-data").basePath("/create").log().all()
.post().then().log().all().extract().response();
It's very simple to consume a RESTFull webservice Api, just follow these simple steps
Step 1: Create a Request Object pointing to the Service
RestAssured.baseURI ="https://myhost.com/xyz";
RequestSpecification request = RestAssured.given();
Step 2: Create a JSON object which contains all the form fields
JSONObject jsonObject = new JSONObject();
jsonObject.put("Form_Field_1", "Input Value 1");
jsonObject.put("Form_Field_2", "Input Value 2");
jsonObject.put("Form_Field_3", "Input Value 3");
jsonObject.put("Form_Field_4", "Input Value 4");
Step 3: Add JSON object in the request body and send the Request
request.header("Content-Type", "application/json");
request.body(jsonObject.toJSONString());
Post the request and check the response
Response response = request.post("/register");
Step 4: Validate the Response
int statusCode = response.getStatusCode();

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