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

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.

Related

Azure Face API not working with local file

I've been trying to send an image from my computer to this API but I only get the following error: {"error":{"code":"InvalidImageSize","message":"Image size is too small."}}
My code is the following.
I have a PostRequestClass with this method:
public void sendImageRequest(String imagePath) {
try {
HttpClient httpClient = new DefaultHttpClient();
File file = new File(imagePath);
FileEntity reqEntity = new FileEntity(file, ContentType.APPLICATION_OCTET_STREAM);
reqEntity.setChunked(false);
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
this.responseResult = EntityUtils.toString(entity);
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
And on my Main is this one:
public class Test {
public static void main(String[] args) throws URISyntaxException {
PostRequest p = new PostRequest(
"https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceAttributes=emotion"
);
p.addHeader("Content-Type", "application/octet-stream");
p.addHeader("Ocp-Apim-Subscription-Key", "my-api-key");
p.sendImageRequest("/Users/user/Desktop/image.jpg");
System.out.println(p.getResponseResult());
}
}
I solved it with the following code:
public void sendImageRequest(String imagePath) {
try {
HttpClient httpClient = new DefaultHttpClient();
File file = new File(imagePath);
FileInputStream fileInputStreamReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileInputStreamReader.read(bytes);
ByteArrayEntity reqEntity = new ByteArrayEntity(bytes, ContentType.APPLICATION_OCTET_STREAM);
request.setEntity(reqEntity);
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
this.responseResult = EntityUtils.toString(entity);
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
Go to https://azure.microsoft.com/en-us/services/cognitive-services/face/ and click "API reference".
It will take you to Face API reference page https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236
The Face API documenatation says "JPEG, PNG, GIF (the first frame), and BMP format are supported. The allowed image file size is from 1KB to 4MB."
Under the heading "Error code and message returned in JSON",
it says, "InValidImageSize" means "The valid image file size should be larger than or equal to 1KB."

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

HttpUrlConnection POST not working as expected [duplicate]

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

posting image Invalid mime type

I am trying to post an image from my galery to the server from my android device.
They are using Python in the back office.
That's what the Back office developper say:
- Django cannot read the file posted by the Android app in request.FILES. iOS does this properly.
- It seems the the Multipart POST does not properly set the key:value required to properly read the requests.
I am getting this error:
{"errorMessage":"","message":"Invalid mime
type","errorCode":0,"success":false}
Any idea why?
Here is my code:
public static final String IMAGE_JPEG = "image/jpeg";
private HttpEntity getImageEntity() throws Exception {
File imageFile;
Uri originalUri = Uri.parse(this.mFileName);
String originalPath = originalUri.getPath();
boolean isEncrypted = originalPath.contains(FileNames.CACHE_DIR.getPath());
// check if file encrypted or not
if (isEncrypted && ImageLoader.IMAGE_CODING_ENABLED) {
File originalImageFile = new File(originalPath);
String decodedPath = CipherUtils.decryptFile(SmartPagerApplication.getInstance(), originalImageFile);
imageFile = new File(decodedPath);
} else {
imageFile = new File(originalPath);
}
InputStream fis = imageFile.toURI().toURL().openStream();
int rotation = PhotoFileUtils.getOrientation(this.mFileName);
if (rotation > 0) {
byte[] data;
Bitmap rotateBitmap = PhotoFileUtils.checkOrientation(BitmapFactory.decodeStream(fis), rotation);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rotateBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
data = stream.toByteArray();
stream.close();
rotateBitmap.recycle();
fis.close();
fis = new ByteArrayInputStream(data);
} else {
// data = IOUtils.toByteArray(fis);
}
return getMultipartEntity(originalUri, fis);
}
private MultipartEntity getMultipartEntity(Uri originalPath, InputStream fis) {
InputStreamBody isb = new InputStreamBody(fis, mMimeType, originalPath.getLastPathSegment());
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,
"----WebKitFormBoundaryzGJGBFWyGteE24tw", Charset.forName("ISO-8859-1"));
multipartEntity.addPart("binaryFile", isb);
return multipartEntity;
}
private String executePost(String url, HttpEntity params) throws ClientProtocolException, IOException {
Log.e("executePost url =" + url);
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "multipart/form-data; boundary="+"----WebKitFormBoundaryzGJGBFWyGteE24tw");
httpPost.addHeader("Cache-Control", "no-cache");
httpPost.setEntity(params);
String response = SmartPagerHTTPClient.getHttpClient().execute(httpPost, new BasicResponseHandler());
return response;
}
I don't have enough reputation to comment, so I have to put this as an answer. In you method getMultipartEntity(), the first line:
InputStreamBody isb = new InputStreamBody(fis, mMimeType, originalPath.getLastPathSegment());
What is the value of mMimeType? Please make sure it's a correct mime type.
This is an OKHttp implementation
first, you need to include it in dependencies:
compile 'com.squareup.okhttp:okhttp:2.4.0'
Actual upload code : Call within an Asynctask
File upload;
upload = new File("<<Your Path to image>>");
Response response;
String finalResponce;
try {
RequestBody body = new MultipartBuilder()
.addFormDataPart("Image", upload.getName(), RequestBody.create(MediaType.parse("image/jpeg"), upload))
.build();
Request request = new Request.Builder()
.url("https://iamin-events.appspot.com/UploadServlet")
.post(body)
.build();
response = new OkHttpClient().newCall(request).execute();
finalResponce = response.body().string();
finalResponce = finalResponce.trim();
mainEventListing.setBackdropUrl(finalResponce);
} catch (Exception e) {
// show error
e.printStackTrace();
}
This is my code for uploading images.The "Content-Type" is like that httpConnection.setRequestProperty("Content-Type", "image/jpeg");
public String doPutUploadImage(File image) throws Exception {
String imageUrl = "http://" + Const.BUCKET_NAME
+ ".oss-cn-hangzhou.aliyuncs.com/" + image.getName();
URL localURL = new URL(imageUrl);
URLConnection connection = localURL.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Host",
Const.BUCKET_NAME.concat(".oss-cn-hangzhou.aliyuncs.com"));
String GMTDate = SignatureMaker.getGMTDate();
if(!GMTDate.contains("+")){
httpConnection.setRequestProperty("Date", GMTDate);
}else{
GMTDate=GMTDate.substring(0, GMTDate.indexOf("+"));
httpConnection.setRequestProperty("Date", GMTDate);
}
httpConnection.setRequestProperty("Content-Encoding", "UTF-8");
httpConnection.setRequestProperty("Content-Type", "image/jpeg");
httpConnection.setRequestProperty("Content-Length",
String.valueOf(image.length()));
httpConnection.setRequestProperty("Authorization",
"OSS "+ ACCESS_ID+ ":"
+ SignatureMaker.makeSignature(ACCESS_KEY, "PUT",
Const.BUCKET_NAME, image, GMTDate));
sendRequest(httpConnection, image);
return imageUrl;
}
Instead of MultipartEntity, I suggest that you use MultipartEntityBuilder with HttpURLConnection. Then, you can refer to my following code (pay attention to ContentType contentType = ContentType.create("image/jpeg");):
...
byte[] bitmapData = byteArrayOutputStream.toByteArray();
String address = "http://192.168.1.100/api/postfile";
String boundary = "----apiclient----" + System.currentTimeMillis();
String mimeType = "multipart/form-data;boundary=" + boundary;
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(boundary);
// Add binary body
if (bitmapData != null) {
ContentType contentType = ContentType.create("image/jpeg"); //CREATE ContentType for the file part
String fileName = "some_file_name.jpeg";
entityBuilder.addBinaryBody("binaryFile", bitmapData, contentType, fileName);
try {
URL url = new URL(address);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", mimeType);
entityBuilder.build().writeTo(urlConnection.getOutputStream());
JSONObject jsonObject = new JSONObject();
try {
if (urlConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
// process urlConnection.getInputStream();
} else {
// process urlConnection.getErrorStream();
}
jsonObject.put("Message", urlConnection.getResponseMessage());
jsonObject.put("Length", urlConnection.getContentLength());
jsonObject.put("Type", urlConnection.getContentType());
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
...
If you still want to use MultipartEntityBuilder with HttpPost, you can refer to the following:
...
byte[] bytes = byteArrayOutputStream.toByteArray();
ContentType contentType = ContentType.create("image/jpeg");
String fileName = "some_filename.jpg";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// Add binary body
builder.addBinaryBody("binaryFile", bytes, contentType, fileName);
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
...
You can find out that addBinaryBody in MultipartEntityBuilder class has many implementations such as:
public MultipartEntityBuilder addBinaryBody(String name, InputStream stream, ContentType contentType, String filename)
public MultipartEntityBuilder addBinaryBody(String name, File file, ContentType contentType, String filename)
public MultipartEntityBuilder addBinaryBody(String name, byte[] b, ContentType contentType, String filename)
...
Hope this helps!
I think this issue is because you are setting Content-Type yourself in code, I once had same issue in my case I just removed the Content-Type and It worked. If you remove the Content-Type, you mean that library will detect its Content-Type based on its type.
just remove this line
httpPost.setHeader("Content-Type", "multipart/form-data; boundary="+"----WebKitFormBoundaryzGJGBFWyGteE24tw");
Here is what i am doing and works fine for me -
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("photo", new FileBody(new File(imagePath), "image/jpeg"));
httppost.setEntity(entity);
According to this org.apache.http documentation Change your mime-type static declaration
public static final String IMAGE_JPEG = "image/jpeg";
to
public static final String IMAGE_JPEG = "image/png";
In addition to the #BNK answer Instead of MultipartEntity, you can use MultipartEntityBuilder with HttpURLConnection. In that you can upload the image as a binary body and there you can set the type and the name:
multiPartEntityBuilder.addBinaryBody(imageName, byteArray, ContentType.create("image/png"), "image.png");
You are probably running your code on Android 4.0.x which has buggy implementation for multipart/form-data (httpclient). This issue has been reported earlier and has a work around here

How to use MultipartEntity in android http post

I have doubt for MultipartEntity.
First it is deprecated or not.
Second how to import MultipartEntity in my project.where to find jars.
I did add jars from Apache httpclient-4.4.1,httpcore-4.4.1,httpmime-4.4.1 into my project libs folder.
But i did not use multipartEntity any mistakes in my side please help me?
I want to upload image from android to spring controller.
Android code is:
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); // Timeout
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("userMO", jsonUserMo));
HttpPost post = new HttpPost(Constants.ROOTURL+"/media/uploadUserImage");
post.setHeader("Content-type", "multipart/form-data; boundary=***");
post.setEntity(new FileEntity(profileImage,"image/jpeg"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
contactLists.append(rd.readLine());
} catch (Exception e) {
e.printStackTrace();
}
My Spring Controller :
#RequestMapping(value = { "/uploadUserImage" }, method = RequestMethod.POST)
public #ResponseBody
String uploadUserImage(#RequestParam(value = "uploadImg") MultipartFile file, #RequestParam("userMO") String userBO, HttpSession session, HttpServletRequest httpServletRequest) {
log.info("hitting image");
UserBO userBo = gson.fromJson(userBO, UserBO.class);
// jboss file location to store images
String filePath = httpServletRequest.getSession().getServletContext().getRealPath("/") + "\\resources\\userImages\\" + userBo.getRingeeUserId() + ".png";
String fileName = file.getOriginalFilename();
try {
if (!file.isEmpty() && file.getBytes().length >= 5242880) {
log.info("file size is "+file.getBytes());
}
if (!file.isEmpty()) {
BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
BufferedImage resizedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
// resizedImage = originalImage.getSubimage(x1, y1, w, h);
File destination = new File(filePath);
// save cropped image
ImageIO.write(resizedImage, "jpeg", destination);
}
} catch (Exception Exp) {
log.info("Upload image failure");
}
return "";
}
I got error in android "http status 400-RequiredMultipartFile parameter 'uploadImg' is not present"
How to solve this?
try {
MultipartEntity entity = new MultipartEntity();
entity.addPart("type", new StringBody("uploadImg"));
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
}
You should add the addPart property with your multipart entity in order to get the additional parameter which your servlet is expecting on the server end. uploadImg in your case is the additional parameter expecting by the server in your request. Hope it will resolve your problem.

Categories

Resources