Sending image from java client to python server - java

I'm new to java and I've been stuck on this problem for the last few days. I'm sending an image from a java client to a python server. I'm getting a 200 request, meaning the connection is being made. But the image is not being read on the server side. I've included the code - any help would be great.
Server Code
def index(request):
data = {"POST REQUEST, INSIDE INDEX, NO URL OR IMAGE SENT": False}
if request.method == "GET":
return HttpResponse("GET REQUEST WORKS. RR.")
if request.method == "POST":
# check to see if an image was uploaded
if request.FILES.get("image", None) is not None:
# grab the uploaded image
image = request.FILES["image"]
# otherwise, assume that a URL was passed in
else:
# grab the URL from the request
url = request.POST.get("url", None)
# if the URL is None, then return an error
if url is None:
return HttpResponse("no URL is specified")
# load the image and convert
image = _grab_image(url=url)
req = image
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
img = cv2.imdecode(arr,-1) # 'load it as it is'
Server = True
Student_Answers = []
image = doc_Scan(img)
if (image == "ERROR"):
return HttpResponse("TAKE ANOTHER PICTURE")
else:
images = crop_answer2(image)
for i in range(0,8):
ans = images[i]
Answer = Input_Image(ans,Server)
print ('Final Answer = ', Answer)
Student_Answers.append(Answer)
Results, score = mark_paper(Server,Student_Answers)
Worded_Respose = "The Student got ", score, " correct"
return HttpResponse(Results, content_type="application/json")
else:
return HttpResponse("NO POST REQUEST")
Client Code
public static void main(String [] args) throws Exception{
String url = "http://########";
// 2. create obj for the URL class
URL obj = new URL(url);
// 3. open connection on the url
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
try {
System.out.println("Reading image from disk. ");
img = ImageIO.read(new File("image.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
baos.flush();
byte[] bytes = baos.toByteArray();
baos.close();
System.out.println("Sending image to server. ");
OutputStream out = con.getOutputStream();
DataOutputStream image = new DataOutputStream(out);
image.writeInt(bytes.length);
image.write(bytes, 0, bytes.length);
System.out.println("Image sent to server. ");
image.close();
// close the output stream
out.close();
}catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
soc.close();
}
// define object for the reply from the server
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
//Get response from server
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
// read in the response from the server
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
System.out.println(inputLine);
}
// close the input stream
in.close();
}
}

Related

Upload image to server efficiently in Android

I have an app that needs to send an image to a server. Right now I'm doing it like this:
//We have a variable "image" that is the Bitmap that we want to send
File imagesFolder = new File(getCacheDir(), "images");
File file = null;
try {
if(imagesFolder.exists() || imagesFolder.mkdirs()) {
file = new File(imagesFolder, "input.jpg");
FileOutputStream stream = new FileOutputStream(file);
//checkWifiOnAndConnected returns true if wifi is on and false if mobile data is being used
image.compress(Bitmap.CompressFormat.JPEG, checkWifiOnAndConnected() ? 90 : 80, stream);
stream.flush();
stream.close();
}
} catch (IOException e) {
Log.d("Error", "IOException while trying to write file for sharing: " + e.getMessage());
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("file", new FileBody(file));
HttpEntity entity = builder.build();
URL url = new URL(serverUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(40000);
conn.setConnectTimeout(40000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setFixedLengthStreamingMode(entity.getContentLength());
conn.addRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
entity.writeTo(os);
os.close();
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK)
Log.e("UPLOAD", "HTTP 200 OK.");
It works, but it's kinda slow, specially when using mobile data (obviously). And I would like to know if there's a more efficient and faster way to send this image.

How to print/read image from REST API call using JAVA

I have one REST URL which if I use in postman it gives me image in response. Now, I'm trying to see the same thing with JAVA code in Eclipse. (I'm looking for either saving image file or showing with JFrame or Applet etc.)
String url = "https://test-api.com/v1/abc.jpg";
// Creating URL Connection
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Defining the request method. It can be GET, POST, PUT, DELETE
con.setRequestMethod("GET");
// Getting the HTTP Response code like 200, 404 etc.
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url + "\n");
System.out.println("Response Code : " + responseCode + "\n");
// Saving response in the Stringbuffer
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
byte bytes[] = String.valueOf(response).getBytes();
InputStream inS = new ByteArrayInputStream(bytes);
int width = 963; //width of the image
int height = 640; //height of the image
BufferedImage image = null;
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
BufferedImage bImageFromConvert = ImageIO.read(inS);
When I run the code, I get the exception like below.
javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:628)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:495)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:621)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1078)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1058)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1352)
Response code comes 200. So, not sure what I'm doing wrong here. Why ImageIO cannot read the inputstream and picking up two SOI marker.
To show an image on the browser using jax-rs you can use this method with the hypothese that you have images folder under resources in your classpath :
#GET
#Path("image")
#Produces({"image/jpeg"})
public Response getImage() {
BufferedImage image = null;
byte[] imageData = null;
try {
//System.out.println("chemin courant : " + ClassLoader.getSystemClassLoader().
// getResource(".").getPath());
image = ImageIO.read(ClassLoaderTestResource.class
.getResourceAsStream("/images/yourimage.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageData = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("image : "+ image);
System.out.println("Image data : "+ imageData);
return Response.ok(new ByteArrayInputStream(imageData)).build();
}
so if you call http://localhost:8080/image for example you will have your image in the browser.

Sending base64 image via http request in Java miss up some chars

I've been trying to send a base64 image using java to NodeJS API, after working and searching for hours I could not know what might cause the following problem, the problem as following:
After logging the base64 image in nodejs I see all + chars replaced by space
Here's a part of the original base64 in Java
f8A0NH2qH+/+hooouAfaof7/wCho+1Q/
and here's is a part of the received image in NodeJS
f8A0NH2qH / hooouAfaof7/wCho 1Q/
I've tried to send an image via POSTMAN and no problem at all.
All steps as following:
1- I am converting an image to base64 using the following snippet
public static String imgToBase64String(final RenderedImage img, final String formatName) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(img, formatName, Base64.getEncoder().wrap(os));
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
public static BufferedImage base64StringToImg(final String base64String) {
try {
return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64String)));
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
And to take screenshot
final Robot robot = new Robot();
final Rectangle r = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
final BufferedImage bi = robot.createScreenCapture(r);
final String base64String = Base64Converter.imgToBase64String(bi, "jpg");
2- I am using Gson library to stringify object
3- I am using bodyParser in NodeJS
4- Sending HTTP request as:
public static void sendPOST(String image) throws Exception {
String POST_PARAMS = "screenShotData";
URL obj = new URL(POST_URL);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setConnectTimeout(5000); // 5 seconds
con.setReadTimeout(5000); // 5 seconds
Gson gson = new Gson();
Http.ScreenShot screenShot = new ScreenShot(); // This is just a class with a string property
screenShot.setImage(image);
POST_PARAMS += gson.toJsonTree(screenShot).getAsJsonObject();
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
byte[] outputBytesArray = POST_PARAMS.getBytes();
os.write(outputBytesArray);
os.flush();
os.close();
int responseCode = con.getResponseCode();
System.out.println("POST Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Object responseObject = gson.fromJson(response.toString(), Object.class);
System.out.println("Res: " + responseObject);
} else {
System.out.println(con.getResponseMessage());
}
}
In URL encoded text, the + character means a space character. For example,
https://example.com/?s=nodejs+bodyparser
sends the s parameter with the value
nodejs bodyparser
(notice the space).
When you do an ordinary form post (the kind browsers do) you use the application/x-www-form-urlencoded data type, meaning the payload of your POST operation looks like a query string. I think you are passing a JSON object as a text string without url-encoding it.
You probably want to use the application/json data type instead. nodejs's body parser detects, from your Content-type header, that it's JSON and parses it correctly.
Try this. (not debugged, sorry.)
string payload = gson.toJsonTree(screenShot).getAsJsonObject();
byte[] outputBytesArray = payload.getBytes();
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(outputBytesArray);
os.flush();
os.close();
You forgot to close the wrapped Base64 encoder stream. Only if you close it the end of the base64 encoded data can be written:
public static String imgToBase64String(final RenderedImage img, final String formatName) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
try (OutputStream wrapped = Base64.getEncoder().wrap(os)) {
ImageIO.write(img, formatName, wrapped);
}
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
I had faced this issue, but I had no authority to change in class or something else.
I had just simply replaced space with +, in most of the cases it was working.

How to get proper response when posting form data to php server using eclipse?

I am posting json data to the server but on getting the response it should be like this
{"id":65,"check":1,"date":"08-Jan-19"}
instead, I am getting this
{"id":"65check=1","check":null,"date":"08-Jan-19"}
This is the code on button click I send json form data to the server but in response, the id value gets attached to check value, how to get the proper response.
Attendance_TimeCheck = "1";
users_identify = "65";
try {
URL urlForPostRequest = new URL("http://xenzet.com/ds/getrec.php");
System.out.println("Instantiated new URL: " + urlForPostRequest);
final long id = Long.valueOf(users_identify);
HttpURLConnection conection = (HttpURLConnection) urlForPostRequest.openConnection();
conection.setDoOutput(true);
conection.setRequestMethod("POST");
conection.setRequestProperty("User-Agent", "Mozilla/5.0");
conection.getOutputStream().write(("id="+id).getBytes(StandardCharsets.UTF_8));
conection.getOutputStream().write(("check="+Attendance_TimeCheck).getBytes(StandardCharsets.UTF_8));
conection.connect();
BufferedInputStream bis = new BufferedInputStream(conection.getInputStream());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int resultBuffer = bis.read();
while (resultBuffer != -1) {
bos.write((byte) resultBuffer);
resultBuffer = bis.read();
}
String result1 = bos.toString();
System.out.println(result1);
} catch (Exception ex) {
ex.printStackTrace();
}
I think the string is being read wrongly.
Check the payload you are passing to the POST request,
conection.getOutputStream().write(("id="+id).getBytes(StandardCharsets.UTF_8));
conection.getOutputStream().write(("check="+Attendance_TimeCheck).getBytes(StandardCharsets.UTF_8));
"id="+id followed by "check="+Attendance_TimeCheck will result to "id":"65check=1"
append the ampersand before the queryparam check to get the desired result,
conection.getOutputStream().write(("&check="+Attendance_TimeCheck).getBytes(StandardCharsets.UTF_8));

How to disable buffering in Java HttpURLConnection for multi-part form post?

(This is for a signed applet and I have decided against HTTPClient to keep my jar very small)
I am using HttpURLConnection to successfully upload a file from the user to a server using multi-part form post.
The problem is that HttpURLConnection is caching the data -- before sending it. So when I am reading from the file and writing to Outputstream, it is merely buffering the data -- and therefore my progress bar, that shows the upload status , is completely wrong. Howevere please note that the form post code works and the file does get uploaded correctly with return code of 200.
So how do I ensure that HttpURLConnection does not cache the data that I am sending to the server ?
Here is my source:
public UploadResponse send(String formPostUrlStr,String fileFieldName,File targetFile, Map<String, String> valuesMap, UploadStatusListener uploadStatusListener) throws Exception{
String sendStr=getBoundaryMessage(Boundary, valuesMap, fileFieldName, targetFile.getName(), valuesMap.get("content-type") );//"image/png") ;
System.out.println(" multi-part start \n "+ sendStr+ " multi-part end \n");
String lenstr=Long.toString((long)(sendStr.length()*2)+ targetFile.length());
System.out.println("Content-Length"+ lenstr);
//Content-Length
URL url= new URL(formPostUrlStr);
long startTime= System.currentTimeMillis();
HttpURLConnection s3Connection = (HttpURLConnection) url.openConnection();
System.out.println("opened url to "+ formPostUrlStr +", connection ok ..");
s3Connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ Boundary);
s3Connection.setRequestProperty("content-length", lenstr);
s3Connection.setDoOutput(true);
s3Connection.setDoInput(true);
s3Connection.setUseCaches(false);
s3Connection.setInstanceFollowRedirects(true);
s3Connection.setAllowUserInteraction(true);
s3Connection.setRequestProperty("User-Agent", "Mozilla/4.5");
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(targetFile.length(), 0);
}
String debugStr= s3Connection.toString();
System.out.println("conmnection "+ debugStr);
DataOutputStream httpOut = new DataOutputStream(s3Connection.getOutputStream());
System.out.println("opened DataOutputStream ok ..");
httpOut.write(sendStr.getBytes());
//httpOut.flush();
System.out.println("httpOut.flush 1 ok ..");
FileInputStream uploadFileReader = new FileInputStream(targetFile);
long totalBytes = uploadFileReader.available();
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(totalBytes, 0);
}
System.out.println(" uploading file with size "+ uploadFileReader.available());
int bufSize = 102400;
long availableBytesToRead;
long totalSent = 0;
while ((availableBytesToRead = uploadFileReader.available()) > 0) {
byte[] bufferBytesRead;
bufferBytesRead = availableBytesToRead >= bufSize ? new byte[bufSize]
: new byte[(int)availableBytesToRead];
int count = uploadFileReader.read(bufferBytesRead);
try{
httpOut.write(bufferBytesRead);
totalSent += ((long) count);
System.out.println(" wrote bytes = "+count+ ", total sent = "+ totalSent +", pendingSize"+ (availableBytesToRead-count) );
}
catch(IOException ioe){
System.out.println(" io exceotion e"+ ioe.getMessage());
throw ioe;
}
//httpOut.flush();
if (uploadStatusListener != null) {
uploadStatusListener.statusUpdate(totalBytes, totalSent);
}
}
// FILE DATA END
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
// form end
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
httpOut.flush();
httpOut.close();
long endTime= System.currentTimeMillis();
System.out.println("Completed Writing Data to S3 Connection in "+ (endTime-startTime)+"ms.,now waiting for rsponse code ");
int code=s3Connection.getResponseCode();
long endTime2= System.currentTimeMillis();
System.out.println("Completed Sendind Data to S3 in "+ (endTime2-startTime)+ "ms., rsponse code time "+ (endTime2-endTime)+"ms. ");
UploadResponse uploadResponse = new UploadResponse();
uploadResponse.setCode(code);
System.out.println(" response code : " + code);
StringBuilder response = new StringBuilder();
byte[] respBuffer = new byte[4096];
if (code > 300) {
if (code == 404) {
throw new Exception("Error 404");
}
BufferedReader err = new BufferedReader(
new InputStreamReader(s3Connection.getErrorStream()));
String ret;
StringBuffer buff = new StringBuffer();
while ((ret = err.readLine()) != null) {
buff.append(ret);
}
uploadResponse.setMessage(buff.toString());
System.out.println(" error :"+ buff.toString());
err.close();
} else {
BufferedReader inp = new BufferedReader(
new InputStreamReader(s3Connection.getInputStream()));
StringBuffer buff = new StringBuffer();
String ret;
while ((ret = inp.readLine()) != null) {
buff.append(ret);
}
inp.close();
uploadResponse.setMessage(buff.toString());
if(buff.toString().contains("fail"))
throw new Exception("Upload failed");
}
System.out.println(response.toString());
return uploadResponse;
}
}
I have the same problem.
I didn't find any other solution than writing my HTTP request on a raw Socket.
Did you find a better workaround ?
EDIT : I just did : we just have to use obj.setFixedLengthStreamingMode(12345) on the HttpURLConnection object obtained from url.openConnection(), where 12345 is the length of POST request body.
As a complementation for the answer that #Antares gave, there is another method setChunkedStreamingMode that is used when you don't know the content size in advance. So when you do a POST request, call that method on the connection:
HttpURLConnection connection = ...
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);
connection.connect();
... connection.getOutputStream();
This will avoid the OutputStream to buffer the entire content before start to send.

Categories

Resources