HttpUrlConnection POST not working as expected [duplicate] - java

lets assume this URL...
http://www.example.com/page.php?id=10
(Here id needs to be sent in a POST request)
I want to send the id = 10 to the server's page.php, which accepts it in a POST method.
How can i do this from within Java?
I tried this :
URL aaa = new URL("http://www.example.com/page.php");
URLConnection ccc = aaa.openConnection();
But I still can't figure out how to send it via POST

Updated answer
Since some of the classes, in the original answer, are deprecated in the newer version of Apache HTTP Components, I'm posting this update.
By the way, you can access the full documentation for more examples here.
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.a-domain.example/foo/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("param-1", "12345"));
params.add(new BasicNameValuePair("param-2", "Hello!"));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
try (InputStream instream = entity.getContent()) {
// do something useful
}
}
Original answer
I recommend to use Apache HttpClient. its faster and easier to implement.
HttpPost post = new HttpPost("http://jakarata.apache.org/");
NameValuePair[] data = {
new NameValuePair("user", "joe"),
new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.
for more information check this URL: http://hc.apache.org/

Sending a POST request is easy in vanilla Java. Starting with a URL, we need t convert it to a URLConnection using url.openConnection();. After that, we need to cast it to a HttpURLConnection, so we can access its setRequestMethod() method to set our method. We finally say that we are going to send data over the connection.
URL url = new URL("https://www.example.com/login");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod("POST"); // PUT is another valid option
http.setDoOutput(true);
We then need to state what we are going to send:
Sending a simple form
A normal POST coming from a http form has a well defined format. We need to convert our input to this format:
Map<String,String> arguments = new HashMap<>();
arguments.put("username", "root");
arguments.put("password", "sjh76HSn!"); // This is a fake password obviously
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
We can then attach our form contents to the http request with proper headers and send it.
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
os.write(out);
}
// Do something with http.getInputStream()
Sending JSON
We can also send json using java, this is also easy:
byte[] out = "{\"username\":\"root\",\"password\":\"password\"}" .getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
os.write(out);
}
// Do something with http.getInputStream()
Remember that different servers accept different content-types for json, see this question.
Sending files with java post
Sending files can be considered more challenging to handle as the format is more complex. We are also going to add support for sending the files as a string, since we don't want to buffer the file fully into the memory.
For this, we define some helper methods:
private void sendFile(OutputStream out, String name, InputStream in, String fileName) {
String o = "Content-Disposition: form-data; name=\"" + URLEncoder.encode(name,"UTF-8")
+ "\"; filename=\"" + URLEncoder.encode(filename,"UTF-8") + "\"\r\n\r\n";
out.write(o.getBytes(StandardCharsets.UTF_8));
byte[] buffer = new byte[2048];
for (int n = 0; n >= 0; n = in.read(buffer))
out.write(buffer, 0, n);
out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
private void sendField(OutputStream out, String name, String field) {
String o = "Content-Disposition: form-data; name=\""
+ URLEncoder.encode(name,"UTF-8") + "\"\r\n\r\n";
out.write(o.getBytes(StandardCharsets.UTF_8));
out.write(URLEncoder.encode(field,"UTF-8").getBytes(StandardCharsets.UTF_8));
out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
We can then use these methods to create a multipart post request as follows:
String boundary = UUID.randomUUID().toString();
byte[] boundaryBytes =
("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8);
byte[] finishBoundaryBytes =
("--" + boundary + "--").getBytes(StandardCharsets.UTF_8);
http.setRequestProperty("Content-Type",
"multipart/form-data; charset=UTF-8; boundary=" + boundary);
// Enable streaming mode with default settings
http.setChunkedStreamingMode(0);
// Send our fields:
try(OutputStream out = http.getOutputStream()) {
// Send our header (thx Algoman)
out.write(boundaryBytes);
// Send our first field
sendField(out, "username", "root");
// Send a seperator
out.write(boundaryBytes);
// Send our second field
sendField(out, "password", "toor");
// Send another seperator
out.write(boundaryBytes);
// Send our file
try(InputStream file = new FileInputStream("test.txt")) {
sendFile(out, "identification", file, "text.txt");
}
// Finish the request
out.write(finishBoundaryBytes);
}
// Do something with http.getInputStream()

String rawData = "id=10";
String type = "application/x-www-form-urlencoded";
String encodedData = URLEncoder.encode( rawData, "UTF-8" );
URL u = new URL("http://www.example.com/page.php");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", type );
conn.setRequestProperty( "Content-Length", String.valueOf(encodedData.length()));
OutputStream os = conn.getOutputStream();
os.write(encodedData.getBytes());

The first answer was great, but I had to add try/catch to avoid Java compiler errors.
Also, I had troubles to figure how to read the HttpResponse with Java libraries.
Here is the more complete code :
/*
* Create the POST request
*/
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user", "Bob"));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
/*
* Execute the HTTP Request
*/
try {
HttpResponse response = httpClient.execute(httpPost);
HttpEntity respEntity = response.getEntity();
if (respEntity != null) {
// EntityUtils to get the response content
String content = EntityUtils.toString(respEntity);
}
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}

A simple way using Apache HTTP Components is
Request.Post("http://www.example.com/page.php")
.bodyForm(Form.form().add("id", "10").build())
.execute()
.returnContent();
Take a look at the Fluent API

I suggest using Postman to generate the request code. Simply make the request using Postman then hit the code tab:
Then you'll get the following window to choose in which language you want your request code to be:

simplest way to send parameters with the post request:
String postURL = "http://www.example.com/page.php";
HttpPost post = new HttpPost(postURL);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", "10"));
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(ent);
HttpClient client = new DefaultHttpClient();
HttpResponse responsePOST = client.execute(post);
You have done. now you can use responsePOST.
Get response content as string:
BufferedReader reader = new BufferedReader(new InputStreamReader(responsePOST.getEntity().getContent()), 2048);
if (responsePOST != null) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
System.out.println(" line : " + line);
sb.append(line);
}
String getResponseString = "";
getResponseString = sb.toString();
//use server output getResponseString as string value.
}

Using okhttp :
Source code for okhttp can be found here https://github.com/square/okhttp.
If you're writing a pom project, add this dependency
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
</dependency>
If not simply search the internet for 'download okhttp'. Several results will appear where you can download a jar.
your code :
import okhttp3.*;
import java.io.IOException;
public class ClassName{
private void sendPost() throws IOException {
// form parameters
RequestBody formBody = new FormBody.Builder()
.add("id", 10)
.build();
Request request = new Request.Builder()
.url("http://www.example.com/page.php")
.post(formBody)
.build();
OkHttpClient httpClient = new OkHttpClient();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// Get response body
System.out.println(response.body().string());
}
}
}

Easy with java.net:
public void post(String uri, String data) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(uri))
.POST(BodyPublishers.ofString(data))
.build();
HttpResponse<?> response = client.send(request, BodyHandlers.discarding());
System.out.println(response.statusCode());
Here is more information:
https://openjdk.java.net/groups/net/httpclient/recipes.html#post

Since java 11, HTTP requests can be made by using java.net.http.HttpClient with less code.
var values = new HashMap<String, Integer>() {{
put("id", 10);
}};
var objectMapper = new ObjectMapper();
String requestBody = objectMapper
.writeValueAsString(values);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://www.example.com/abc"))
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

Call HttpURLConnection.setRequestMethod("POST") and HttpURLConnection.setDoOutput(true); Actually only the latter is needed as POST then becomes the default method.

I recomend use http-request built on apache http api.
HttpRequest<String> httpRequest = HttpRequestBuilder.createPost("http://www.example.com/page.php", String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();
public void send(){
String response = httpRequest.execute("id", "10").get();
}

Related

How to send post request with x-www-form-urlencoded body

How in java, can I send a request with x-www-form-urlencoded header. I don't understand how to send a body with a key-value, like in the above screenshot.
I have tried this code:
String urlParameters =
cafedra_name+ data_to_send;
URL url;
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", "" +
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
But in the response, I don't receive the correct data.
As you set application/x-www-form-urlencoded as content type so data sent must be like this format.
String urlParameters = "param1=data1&param2=data2&param3=data3";
Sending part now is quite straightforward.
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
String request = "<Url here>";
URL url = new URL( request );
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(postDataLength ));
conn.setUseCaches(false);
try(DataOutputStream wr = new DataOutputStream(conn.getOutputStream())) {
wr.write( postData );
}
Or you can create a generic method to build key value pattern which is required for application/x-www-form-urlencoded.
private String getDataString(HashMap<String, String> params) throws UnsupportedEncodingException{
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
For HttpEntity, the below answer works
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("email", "first.last#example.com");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
For reference:
How to POST form data with Spring RestTemplate?
Use Java 11 HttpClient
The HTTP Client was added in Java 11. It can be used to request HTTP resources over the network. It supports HTTP/1.1 and HTTP/2, both synchronous and asynchronous programming models, handles request and response bodies as reactive-streams, and follows the familiar builder pattern.
https://openjdk.java.net/groups/net/httpclient/intro.html
HttpClient client = HttpClient.newHttpClient();;
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(targetUrl))
.POST(urlParameters)
.headers("Content-Type", "application/x-www-form-urlencoded")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Problem with the Response!
I had a similar issue when I was sending the request of media type application/x-www-form-urlencoded from Postman I was receiving a correct response.
However, when sending the request using code, I was receiving jargon somewhat like:
�-�YO�`:ur���g�
.n��l���u)�i�h3J%Gl�?����k
What I tried:
Out of frustration for multiple days tried all the possible solutions from changing character sets to changing header values to code changes and whatnot.
Solution lies in Postman.
Select Java-OkHttp
Copy the code and paste it into IDE.
That's it.
Reference for HttpOk:
https://www.vogella.com/tutorials/JavaLibrary-OkHttp/article.html
string urlParameters = "param1=value1&param2=value2";
string _endPointName = "your url post api";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(_endPointName);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
httpWebRequest.Headers["ContentType"] = "application/x-www-form-urlencoded";
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) =>
{
return true;
};
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(urlParameters);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Building off of Navoneel's answer, I like to use StreamEx's EntryStream.
Here is Naveoneel's method re-written.
private String getDataString(HashMap<String, String> params)
{
return EntryStream.
of(data).
mapKeys(key -> URLEncoder.encode(key, StandardCharsets.UTF_8)). // Encode the keys
mapValues(value -> URLEncoder.encode(value, StandardCharsets.UTF_8)). // Encode the values
join("="). // Create a key=value
joining("&"); // Assemble into key1=value1&key2=value2...
}

How do I use the apache httpClient API to send file + api key and other parameters as a single request?

I have started to test http client apache API. I need it because I would like to send requests and to receive responses to virustotal API. Virus total API requires to parameters in the post request:
the api key value (a unique value for each user)
the file itself as I understood from their website.
For example:
>>> url = "https://www.virustotal.com/vtapi/v2/url/scan"
>>> parameters = {"url": "http://www.virustotal.com",
... "apikey": "-- YOUR API KEY --"}
>>> data = urllib.urlencode(parameters)
>>> req = urllib2.Request(url, data)
At the moment, I am trying to do the same thing in Java instead of Python. Here is a part of my source code commented to guide throughout the steps:
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//create post request
HttpPost request = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");
//http json header
request.addHeader("content-type", "application/json");
String str = gson.toJson(param);
String fileName = UUID.randomUUID().toString() + ".txt";
try {
//API key
StringEntity entity = new StringEntity(str);
Writer writer = new BufferedWriter(new FileWriter(fileName));
writer.write(VirusDefinitionTest.malware());
request.setEntity(entity);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
FileBody fileBody = new FileBody(new File(fileName));
builder.addTextBody("my_file", fileName);
HttpEntity entity = builder.build();
request.setEntity(entity);
HttpResponse response;
try {
response = httpClient.execute(request);
...
Unfortunately, I receive HTTP/1.1 403 Forbidden. Obviously, the error is somewhere in the entities but I cannot find how to do it. Any help would be deeply welcomed.
This worked for me with Apache 4.5.2 HttpClient:
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");
FileBody bin = new FileBody(new File("... the file here ..."));
// the API key here
StringBody comment = new StringBody("5ec8de.....", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("apikey", comment)
.addPart("file", bin)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("ToString:" + EntityUtils.toString(resEntity));
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
The important part was the reqEntity which had to have two specifically named fields, "apikey", and "file". Running this with a valid API key gives me the expected response from the API.
The problem seems to be that first you add explicit "content-type" header which is "application/json" and at the end you send the Muiltipart entity. You need to add all the parameters and the file to the Muiltipart entity. Now the parameters are not send, because they are overwritten by Muiltipart entity:
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//create post request
HttpPost request = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");
//http json header
request.addHeader("content-type", "application/json");
String str = gson.toJson(param);
String fileName = UUID.randomUUID().toString() + ".txt";
try {
//API key
StringEntity entity = new StringEntity(str);
Writer writer = new BufferedWriter(new FileWriter(fileName));
writer.write(VirusDefinitionTest.malware());
// --> You set parameters here !!!
request.setEntity(entity);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
FileBody fileBody = new FileBody(new File(fileName));
builder.addTextBody("my_file", fileName);
HttpEntity entity = builder.build();
// --> You overwrite the parameters here !!!
request.setEntity(entity);
HttpResponse response;
try {
response = httpClient.execute(request);

"Decoding error, image format unsupported" in Microsoft Face API

I'm trying to use Microsoft Face API. For that I have the following code that was given by Microsoft as a sample (at the end of this page https://dev.projectoxford.ai/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236):
HttpClient httpclient = HttpClients.createDefault();
try {
URIBuilder builder = new URIBuilder("https://api.projectoxford.ai/face/v1.0/detect");
builder.setParameter("returnFaceId", "false");
builder.setParameter("returnFaceLandmarks", "false");
builder.setParameter("returnFaceAttributes", "age,gender");
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/octet-stream");
request.setHeader("Ocp-Apim-Subscription-Key", "...");
String body = Base64.encodeBase64String(img);
StringEntity reqEntity = new StringEntity(body);
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
return JsonParser.parse(EntityUtils.toString(entity));
}
} catch (URISyntaxException | IOException | ParseException e) {
System.out.println(e.getMessage());
}
return null;
but I get the following error:
{"error":{"code":"InvalidImage","message":"Decoding error, image format unsupported."}}
The image that I am using for tests is this one:
http://www.huntresearchgroup.org.uk/images/group/group_photo_2010.jpg
(found it on the internet in a quick search)
It respect all the requisits set by Microsoft, size and format... If I use it in the site it works https://www.projectoxford.ai/demo/face#detection
The String body from the convertion of my array of bytes to a string in base64 is also ok, I test it in this website: http://codebeautify.org/base64-to-image-converter
The error message it's quite simple, but I fail to see where I am worng. Anyone might know whats the problem?
UPDATE
The variable img:
img = Files.readAllBytes(Paths.get(imgPath));
I managed to discover the problem... Instead of:
String body = Base64.encodeBase64String(img);
StringEntity reqEntity = new StringEntity(body);
request.setEntity(reqEntity);
I needed to do:
ByteArrayEntity reqEntity = new ByteArrayEntity(img, ContentType.APPLICATION_OCTET_STREAM);
request.setEntity(reqEntity);
I think that the Documentation is outdated...
I made the following change. Instead of sending an encoded image, I am sending the URL for the image.
request.setHeader("Content-Type", "application/json");
request.setHeader("Ocp-Apim-Subscription-Key", "{YOUR_FACES_API_KEY}");
StringEntity reqEntity = new StringEntity("{ \"url\":\"http://www.huntresearchgroup.org.uk/images/group/group_photo_2010.jpg\" }");
request.setEntity(reqEntity);
This gets the response:
[{"faceRectangle":{"top":878,"left":2718,"width":312,"height":312},"faceAttributes":{"gender":"male","age":28.5}},{"faceRectangle":{"top":593,"left":573,"width":310,"height":310},"faceAttributes":{"gender":"male","age":27.5}},{"faceRectangle":{"top":1122,"left":1014,"width":294,"height":294},"faceAttributes":{"gender":"female","age":27.7}},{"faceRectangle":{"top":915,"left":1773,"width":277,"height":277},"faceAttributes":{"gender":"female","age":36.7}},{"faceRectangle":{"top":566,"left":1276,"width":269,"height":269},"faceAttributes":{"gender":"male","age":40.7}},{"faceRectangle":{"top":677,"left":2134,"width":257,"height":257},"faceAttributes":{"gender":"female","age":35.2}}]
Will work on sending an encoded image soon. Will update this post accordingly.
EDIT:
Downloading image from URL
String base64Img = null;
byte[] bytes = null;
String imgBinaryString = null;
String base64ImgBinaryString = null;
try {
URL url = new URL("http://www.businessstudynotes.com/wp-content/uploads/2015/09/Role-of-Group.jpg");
//"http://www.huntresearchgroup.org.uk/images/group/group_photo_2010.jpg");
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
bytes = baos.toByteArray();
StringBuilder sb = new StringBuilder();
for (byte by: bytes)
sb.append(Integer.toBinaryString(by & 0xFF));
imgBinaryString = sb.toString();
base64Img = Base64.getEncoder().encodeToString(bytes);
byte[] base64Bytes = base64Img.getBytes("UTF-8");
sb = new StringBuilder();
for (byte by: base64Bytes) {
sb.append(Integer.toBinaryString(by & 0xFF));
}
base64ImgBinaryString = sb.toString();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
System.out.println("Download issue");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("ImageIO issue");
e.printStackTrace();
}
imgBinaryString contains a binary representation of the image; base64ImgBinaryString contains a binary representation of the Base 64 representation of the image.
To upload this image...
URI uri = builder.build(); // builder = new URIBuilder("https://api.projectoxford.ai/face/v1.0/detect");
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/octet-stream");
request.setHeader("Ocp-Apim-Subscription-Key", "{YOUR_FACES_API_KEY");
StringEntity reqEntity = new StringEntity(base64ImgBinaryString);
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
Setting the StringEntity to both imgBinaryString and base64ImgBinaryString results in the same response...
{"error":{"code":"InvalidImage","message":"Decoding error, image format unsupported."}}
Now, the good stuff. This works...
ByteArrayEntity reqEntity = new ByteArrayEntity(bytes, ContentType.APPLICATION_OCTET_STREAM);
request.setEntity(reqEntity);
where bytes is the byte-array for the image; but a Base64 representation of this doesn't work. Someone really needs to update the documentation.
You could take a look at CognitiveJ, an open source library that will handle the communications & interactions with the MS faces API. If you don't want to use the library then you can have a look at the code to see what the REST API expects.
(disclosure - I'm the author of the library).
import okhttp3.*;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
doRequest();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void doRequest() throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"),
new File(".//src//main//java//Archivo_001.png"));
Request request = new Request.Builder()
.url("https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise")
.post(body)
.addHeader("Ocp-Apim-Subscription-Key", "1d88f949af3443ea8cc16b7146bd7501")
.addHeader("Content-Type", "application/json")
.addHeader("cache-control", "no-cache")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
}
Hoping that this answer would be helpful to someone in the future, since I struggled with this quite a bit before finding this thread and realising the issue was on the documentation.
I managed to get the octet-stream type request working with HttpClient and RestTemplate.
HttpClient version:
HttpClient httpclient = HttpClients.createDefault();
try
{
URIBuilder builder = new URIBuilder(String.format("https://%s.api.cognitive.microsoft.com/face/v1.0/detect", region));
List<String> faceAttributes = Arrays.asList("age","gender","headPose","smile","facialHair","glasses","emotion","hair","makeup","occlusion","accessories","blur","exposure","noise");
String faceAttributesCommaSeparated = String.join(",", faceAttributes);
builder.setParameter("returnFaceId", "true");
builder.setParameter("returnFaceLandmarks", "false");
builder.setParameter("returnFaceAttributes", faceAttributesCommaSeparated);
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/octet-stream");
request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
ByteArrayEntity reqEntity = new ByteArrayEntity(fileContentBytes, ContentType.APPLICATION_OCTET_STREAM);
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = (HttpEntity) response.getEntity();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
RestTemplate:
private RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.add("Ocp-Apim-Subscription-Key", subscriptionKey);
List<String> faceAttributes = Arrays.asList("age","gender","headPose","smile","facialHair","glasses","emotion","hair","makeup","occlusion","accessories","blur","exposure","noise");
String faceAttributesCommaSeparated = String.join(",", faceAttributes);
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
paramsMap.add("returnFaceId", "true");
paramsMap.add("returnFaceLandmarks", "false");
paramsMap.add("returnFaceAttributes", faceAttributesCommaSeparated);
HttpEntity<byte[]> requestEntity = new HttpEntity<>(fileContentBytes, headers);
ResponseEntity<String> response = null;
try {
response = restTemplate.exchange(
String.format("%s/face/v1.0/detect", endpoint),
HttpMethod.POST,
requestEntity,
String.class,
paramsMap
);
} catch (HttpClientErrorException e) {
e.printStackTrace();
}
I left some specific values as variables but the gist of it should be clear. I will be using the restTemplate version in production code with a few minor changes.

API call by HTTP POST method without using parameter name for the body

I'm using Java. How I can make a HTTP POST call API and inform in body only "JSON" value (without parameter name)?
Per example call this URL: https://api.nimble.com/api/v1/contact?access_token=12123486db0552de35ec6daa0cc836b0 (POST METHOD) and in body would only have this (without parameter name):
{'fields':{'first name': [{'value': 'Jack','modifier': '',}],'last name': [{'value': 'Daniels','modifier': '',}],'phone': [{'modifier': 'work','value': '123123123',}, {'modifier':'work','value': '2222',}],},'type': 'person','tags': 'our customers\,best'}
If this is correct, someone could give me an example please?
Using this library for the network part : http://hc.apache.org/
Using this library for the json part : http://code.google.com/p/google-gson/
Example :
public String examplePost(DataObject data) {
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost httppost = new HttpPost("your url");
// serialization of data into json
Gson gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(data);
httppost.addHeader("content-type", "application/json");
// creating the entity to send
ByteArrayEntity toSend = new ByteArrayEntity(json.getBytes());
httppost.setEntity(toSend);
HttpResponse response = httpClient.execute(httppost);
String status = "" + response.getStatusLine();
System.out.println(status);
HttpEntity entity = response.getEntity();
InputStream input = entity.getContent();
StringWriter writer = new StringWriter();
IOUtils.copy(input, writer, "UTF8");
String content = writer.toString();
// do something useful with the content
System.out.println(content);
writer.close();
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
httpClient.getConnectionManager().shutdown();
}
}
Hope it helps.

Java httpclient to log into website and download file - Session Problems!

I log on to a website using the POST method (httpclient from apache).
I let the HttpClient execute the HttpPost, let the connection manager release it and then I want to post a GET message that opens a php-URL file to download a pdf.
But all I get is the html file of a "session expired" page
(println: File: index_GT_neu.html?fehlermeldung=fehler_sessioncheck)
I was thinking that once i used the instance of HttpClient to log on at the site, I would be able to open another URL that is only available after log on. But appearently I was wrong.
Somebody could give me a hint?
Thanks in advance!
This is what my main looks like:
// prepare post method
HttpPost post = new HttpPost("http://epaper02.niedersachsen.com/epaper/index_GT_neu.html");
//prepare get method
HttpGet httpget = new HttpGet("http://epaper01.niedersachsen.com/epaper/getfile.php?pdf=0114_GTB_HP_01.pdf&zeitung=GT&ekZeitung=&Y=11&M=01&D=14&C=0");
// add parameters to the post method
List <NameValuePair> parameters = new ArrayList <NameValuePair>();
parameters.add(new BasicNameValuePair("username", "test"));
parameters.add(new BasicNameValuePair("passwort", "test"));
UrlEncodedFormEntity sendentity = new UrlEncodedFormEntity(parameters, HTTP.UTF_8);
post.setEntity(sendentity);
// create the client and execute the post method
HttpClient client = new DefaultHttpClient();
HttpResponse postResponse = client.execute(post);
//Output the Response from the POST
System.out.print(convertInputStreamToString(postResponse.getEntity().getContent()));
//releasing POST
EntityUtils.consume(postResponse.getEntity());
//Execute get
HttpContext context = new BasicHttpContext();
HttpResponse getResponse = client.execute(httpget, context);
System.out.println("Statusline: " + getResponse.getStatusLine());
if (getResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
throw new IOException(getResponse.getStatusLine().toString());
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
String currentUrl = URLDecoder.decode(currentReq.getURI().toString(), "UTF-8");
int i = currentUrl.lastIndexOf('/');
String fileName = null;
if (i < 0) {
fileName = currentUrl;
} else {
fileName = currentUrl.substring(i + 1);
}
System.out.println("File: " + fileName);
//Create file
OutputStream os = new FileOutputStream( fileName);
InputStream is = getResponse.getEntity().getContent();
byte[] buf = new byte[4096];
int read;
while ((read = is.read(buf)) != -1) {
os.write(buf, 0, read);
}
os.close();
client.getConnectionManager().shutdown();
By default, DefaultHttpClient does not have a cookie store. A cookie store is needed in order to store cookies that are populated initially or that are obtained while interacting with the HTTP client. As soon as digging into this topic you will start to think about the scope/sharing of cookies.
You can enable the cookie store with one additional line of code:
DefaultHttpClient client = new DefaultHttpClient();
client.setCookieStore(new BasicCookieStore());
I know, this might be a bit late, still HTH.
I am not familiar with this library but try creating context before calling the post and reuse the same context for the get:
HttpContext context = new BasicHttpContext();
// create the client and execute the post method
HttpClient client = new DefaultHttpClient();
HttpResponse postResponse = client.execute(post,context);
...
HttpResponse getResponse = client.execute(httpget, context);

Categories

Resources