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
Related
I am sending a HttpURLConnection request to server and trying to send a file. I am able to send file from client side but not sure how can i parse it on the server side.
My code on client side is below.
private void createRequestInCHESS(String sRequestId, String sLastUpdated) {
String boundary = "xyz";
String crlf = "\r\n";
String twoHyphens = "--";
String attachmentName = "file";
String attachmentFileName = "testFile.xlsx";
try {
File file = new File("c:\\MFGREQ-7.xlsx");
URL url = new URL(chess.getMfgRequestURL() + "/createRequest");
HttpURLConnection httpConnecton = (HttpURLConnection) url.openConnection();
httpConnecton.setRequestMethod(REQUEST_METHOD_POST);
httpConnecton.setRequestProperty("Accept", "application/json");
httpConnecton.setRequestProperty("Cache-Control", "no-cache");
httpConnecton.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
httpConnecton.setRequestProperty("id", sRequestId);
httpConnecton.setRequestProperty("lastModified", sLastUpdated);
httpConnecton.setDoOutput(true);
DataOutputStream outStream = new DataOutputStream(httpConnecton.getOutputStream());
outStream.writeBytes(twoHyphens + boundary + crlf);
outStream.writeBytes("Content-Disposition: form-data; name=\"" +
attachmentName + "\";filename=\"" + attachmentFileName + "\"" + crlf);
outStream.writeBytes(crlf);
byte[] bytes = Files.readAllBytes(file.toPath());
outStream.write(bytes);
outStream.flush();
outStream.close();
getResponseString(httpConnecton);
} catch (MalformedURLException me) {
me.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
server side code is given below. What can I use to retrive file sent from request.
#POST
#Path("/createRequest")
public Response createRequest(#Context HttpServletRequest request) {
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(request.getInputStream()))) {
StringBuilder sbPayload = new StringBuilder();
String sLine;
while ((sLine = reader.readLine()) != null) {
sbPayload.append(sLine);
sbPayload.append(System.lineSeparator());
}
String data = sbPayload.toString();
// how do i retrieve file here ?
}
You really don't want to parse that yourself. Use the https://commons.apache.org/proper/commons-fileupload/
Then you can just write.
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8"); // Might be needed, depending on exact setup.
java.util.List<FileItem> items = upload.parseRequest(request);
And then items is the list of uploaded files.
Here is my answer. I have used org.glassfish.jersey.media.multipart.MultiPart on client side.
Client client = ClientBuilder.newBuilder().register(MultiPartFeature.class).build();
WebTarget webTarget = client.target(chess.getMfgRequestURL() + "/createRequest")
.queryParam("id", sRequestId)
.queryParam("lastModified", sLastUpdated);
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
#SuppressWarnings("resource")
MultiPart multiPart = new FormDataMultiPart()
.field("json", jsonObj, MediaType.APPLICATION_JSON_TYPE) // json goes here
.bodyPart(fileDataBodyPart); // file goes here
multiPart.bodyPart(fileDataBodyPart);
Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(multiPart, multiPart.getMediaType()));
On server side, this is how I have parsed:
#POST
#Path("/createRequest")
#Consumes("multipart/form-data")
public Response createRequest(#Context HttpServletRequest request, #Multipart InputStream uploadedInputStream) throws Exception {
JsonObjectBuilder requestBuilder = null;
try {
String tempDir = "C:\\Users";
String filename = "test.xlsx";
File checkinFile = new File(tempDir, filename);
OutputStream out = new FileOutputStream(checkinFile);
IOUtils.copyStream(uploadedInputStream, out);
}catch (Exception e) {
String errorMessage = e.getMessage();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).build();
}
I see almost all webservice for android are written in PHP code. With Java I found an example of a rest service to upload image. I coded follow that code but when run test on my android device and Advanced RESTClient of chorme, I get error: HTTP Status 500 - Internal Server Error: Servlet.init () for servlet [Jersey REST Service] threw exception.. My URL: "http://srv.triaxvn.com:8080/logisticwsm/file/image-upload"
In android I use code:
#Override
protected String doInBackground(Void... params) {
return uploadFile();
}
#SuppressWarnings("deprecation")
private String uploadFile() {
File sourceFile = new File(filePath);
String fileName = sourceFile.getName();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(FILE_UPLOAD_URL);
MultipartEntity entity = new MultipartEntity();
// Extra parameters if you want to pass to server
entity.addPart("fileDescription", new StringBody(""));
entity.addPart("fileName", new StringBody(fileName != null ? fileName : sourceFile.getName()));
// Adding file data to http body
FileBody fileBody = new FileBody(sourceFile, "application/octect-stream") ;
entity.addPart("attachment", fileBody);
//totalSize = entity.getContentLength();
httppost.setEntity(entity);
// Making server call
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
// Server response
responseString = EntityUtils.toString(r_entity);
} else {
responseString = "Error occurred! Http Status Code: "
+ statusCode;
}
My Restful web service code:
#Path("/file")
public class UploadFile {
private final String UPLOADED_FILE_PATH = "c:\\uploaded";
#POST
#Path("/image-upload")
#Consumes("multipart/form-data")
public Response uploadFile(MultipartFormDataInput input) throws IOException
{
//Get API input data
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
//Get file name
String fileName = uploadForm.get("fileName").get(0).getBodyAsString();
//Get file data to save
List<InputPart> inputParts = uploadForm.get("attachment");
for (InputPart inputPart : inputParts)
{
try
{
//Use this header for extra processing if required
#SuppressWarnings("unused")
MultivaluedMap<String, String> header = inputPart.getHeaders();
// convert the uploaded file to inputstream
InputStream inputStream = inputPart.getBody(InputStream.class, null);
byte[] bytes = IOUtils.toByteArray(inputStream);
// constructs upload file path
fileName = UPLOADED_FILE_PATH + fileName;
writeFile(bytes, fileName);
System.out.println("Success !!!!!");
}
catch (Exception e)
{
e.printStackTrace();
return Response.status(200).entity("Uploaded file name : "+e.getMessage()).build();
}
}
return Response.status(200)
.entity("Uploaded file name : "+ fileName).build();
}
//Utility method
private void writeFile(byte[] content, String filename) throws IOException
{
File file = new File(filename);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fop = new FileOutputStream(file);
fop.write(content);
fop.flush();
fop.close();
}
I do not know the error caused from by android code or Server Restful code and how to fix it
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.
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();
}
I am developing an Android applicaiton with AppEngine backend. I am creating the server part with Google Cloud Endpoints in Java. My problem is that I cannot send a Bitmap from the client to the server.
I used the answer from this question but even if the client part does not seem to have any problems at all, the server part does not receive the data at all. I also think this solution might be a bit complicated and that it might work a different, easier way, however this is my first time implementing a server and first time sending a picture to it so I accept any good tips on this. Thanks!
Here is my code:
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
String charset = "UTF-8";
HttpURLConnection connection = (HttpURLConnection) new URL("https://path_to_my_app/_ah/api/registration/v1/uploadImage").openConnection();
connection.setDoOutput(true);
connection.setReadTimeout(60000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + somename + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).flush();
BufferedReader reader = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byteArray = stream.toByteArray();
try {
reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray), charset));
for (String line; (line = reader.readLine()) != null;) {
writer.append(line).append(CRLF);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.flush();
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
}
finally
{
if (writer != null)
{
writer.close();
}
}
The server part:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public void uploadImage(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ServletFileUpload fileUpload = new ServletFileUpload();
try
{
FileItemIterator iterator = fileUpload.getItemIterator(request);
while(iterator.hasNext()){
FileItemStream itemStream = iterator.next();
String fieldName = itemStream.getFieldName();
log.info("field name:"+fieldName);
InputStream stream = itemStream.openStream();
String result = getStringFromInputStream(stream);
log.info("result: "+result);
stream.close();
}
}
catch (FileUploadException e)
{
e.printStackTrace();
}
}
I am getting 204 no Content type now.
I did it!
I think this is not the best way of doing it but it´s working so I am fine until I get a better solution.
So I take the Bitmap image and convert it to String:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byte[] bitmapByte = outputStream.toByteArray();
String stringEncodedImage = Base64.encodeToString(bitmapByte, Base64.DEFAULT);
Then I create a httpPostRequest and set a JsonObject to it with the image converted to String in it.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://my_app_path/_ah/api/registration/v1/uploadImage");
JSONObject jsonObject = new JSONObject();
jsonObject.put("image",stringEncodedImage);
StringEntity stringEntity = new StringEntity(jsonObject.toString());
httpPost.addHeader("Content-Type", "application/json");
httpPost.setEntity(stringEntity);
HttpResponse response = httpClient.execute(httpPost);
On the server side, in my Endpoint, I do this:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public JSONObject uploadImage(JSONObject request) throws IOException
{
String imageInString = (String) request.get("image");
Blob blob = new Blob(imageInString.getBytes());
....save blob and do whatever you want...
}
The same goes the other way. I pack Blob into JsonObject and send it over.