Http request - already connected - java

Basically I've been using these particular lines of code for quite some time and never had problems with it. Nothing's been touched but now I'm getting
IllegalStateException - Already connected
exactly after I set conn.setUsesCaches(false)
public void PutImageToS3(String signedUrl, Bitmap image) throws WampNetworkException, IOException {
URL url = new URL(signedUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getDoOutput();
conn.setUseCaches(false);
conn.setRequestMethod("PUT");
conn.addRequestProperty("Content-Type", "image/jpeg");
conn.addRequestProperty("Connection", "close");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
image.compress(Bitmap.CompressFormat.JPEG, 100, out);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Failed to upload image to S3: "
+ conn.getResponseCode() + conn.getResponseMessage() + "\r\n");
}
out.flush();
out.close();
conn.disconnect();
}

Write this code in try-finally block and then try
public void PutImageToS3(String signedUrl, Bitmap image) throws WampNetworkException, IOException {
try{
URL url = new URL(signedUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getDoOutput();
conn.setUseCaches(false);
conn.setRequestMethod("PUT");
conn.addRequestProperty("Content-Type", "image/jpeg");
conn.addRequestProperty("Connection", "close");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
image.compress(Bitmap.CompressFormat.JPEG, 100, out);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Failed to upload image to S3: "
+ conn.getResponseCode() + conn.getResponseMessage() + "\r\n");
}
}
finally{
out.flush();
out.close();
conn.disconnect();
}
}

You need to write the request before getting the response code.
Move the close() before getResponseCode(), and remove the redundant flush().
NB Why are you calling getDoOutput() and ignoring the result?

Amazing solution has been found! There was a problem with the router today so uploading is hell. Once switched to internet from provider it worked like a charm :) GG!

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.

Must I Get The Response Code From The Server?

I have the following code
URL url = new URL(pushURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/restService");
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
if(conn.getResponseCode() == 200){
logger.debug("Success");
} else {
logger.debug("Time out set for 30 seconds");
}
String input = writer.getBuffer().toString();
OutputStream os = conn.getOutputStream();
If I am not interested in the response from the server, can I remove the following code?
if(conn.getResponseCode() == 200){
logger.debug("Success");
} else {
logger.debug("Time out set for 30 seconds");
}
Considering that the code, in it's entirety as it is, causes a java.net.ProtocolException, is there a way to still grab the server response and execute conn.getOutputStream();? In what order? What are the consequences of not obtaining the response aside from the obvious reporting concerns?
The problem is that once you get the response code, you have sent your post. In your code, you don't write anything to the output stream before you get the response. So, you are essentially sending nothing over the post (just that header info), getting the response code, and then trying to write to it again, which is not allowed. What you need to do is write to the output stream first, and then get the response code like so:
public static void main(String[] args) throws IOException {
URL url = new URL(pushURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/restService");
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
String input = writer.getBuffer().toString();
OutputStream os = conn.getOutputStream();
for (char c : input.toCharArray()) {
os.write(c);
}
os.close();
if(conn.getResponseCode() == 200){
System.out.println("Success");
} else {
System.out.println("Time out set for 30 seconds");
}
}
Here's a little tutorial:
Reading and Writing Tutorial

Java Post Connection Using Try with Resources

I want to implement the code for handling POST requests using try with resources.
Following is my code:
public static String sendPostRequestDummy(String url, String queryString) {
log.info("Sending 'POST' request to URL : " + url);
log.info("Data : " + queryString);
BufferedReader in = null;
HttpURLConnection con = null;
StringBuilder response = new StringBuilder();
try{
URL obj = new URL(url);
con = (HttpURLConnection) obj.openConnection();
// add request header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("Content-Type", "application/json");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(queryString);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
log.info("Response Code : " + responseCode);
if (responseCode >= 400)
in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
else
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
}catch(Exception e){
log.error(e.getMessage(), e);
log.error("Error during posting request");
}
finally{
closeConnectionNoException(in,con);
}
return response.toString();
}
I have the following concerns for the code:
How to introduce conditional statements in try with resources for the above scenario?
Is there a way to pass on the connection in try with resources? (It can be done using nested try-catch blocks since URL and HTTPConnection is not AutoCloseable, which itself is not a compliant solution)
Is using try with resources for the above problem is a better approach?
Try this.
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
try (AutoCloseable conc = () -> con.disconnect()) {
// add request headers
try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
wr.writeBytes(queryString);
}
int responseCode = con.getResponseCode();
try (InputStream ins = responseCode >= 400 ? con.getErrorStream() : con.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(ins))) {
// receive response
}
}
() -> con.disconnect() is a lambda expression which execute con.disconnect() at finally stage of the try statement.
1: You can use conditional statements inside try with resources statement also. Unfortunately you have to define new variable for this block and cannot use a predefined variable. ( variable in in your code)
try (BufferedReader in = (responseCode >= 400 ? new BufferedReader(new InputStreamReader(con.getErrorStream())) : new BufferedReader(new InputStreamReader(con.getInputStream())))) {
// your code for getting string data
}
2: I'm not sure HttpUrlConnection is AutoCloseable, So it might be a good idea to call the disconnect() yourself. I'm open to any suggestion on this one.
3: try with resources will definitely help you in managing the resources. But if you're confident that you're releasing the resources properly after use, then your code is fine.

File is not uploded after removing System.out.println("response :: " + conn.getResponseMessage());

Following is my function to upload file GCS :
public void fileUpload(InputStream streamData, String fileName,
String content_type) throws Exception {
byte[] utf8Bytes = fileName.getBytes("UTF8");
fileName = new String(utf8Bytes, "UTF8");
URL url = new URL("http://bucketname.storage.googleapis.com"+"/"+"foldername/"+fileName);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("PUT");
conn.setRequestProperty("Accept", "application/x-www-form-urlencoded");
conn.setRequestProperty("Authorization", "OAuth " + GcsToken.getAccessToken());
conn.setRequestProperty("x-goog-meta-FileName", fileName);
conn.setRequestProperty("x-goog-meta-ContentType", content_type);
OutputStream os = conn.getOutputStream();
BufferedInputStream bfis = new BufferedInputStream(streamData);
byte[] buffer = new byte[1024];
int bufferLength = 0;
// now, read through the input buffer and write the contents to the file
while ((bufferLength = bfis.read(buffer)) > 0) {
os.write(buffer, 0, bufferLength);
}
System.out.println("response :: " + conn.getResponseMessage());// ?????
}
This code works fine to uplaod file, but
After removing last Sysout , it is not uploading file
System.out.println("response :: " + conn.getResponseMessage());
what is reason behind this ?
any help ?
thnaks
You need to close your OutputStream to indicate that you've finished writing the request body:
os.close();
You should also check the response code of the request:
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
// Error handling code here.
}
The reason it was working before is because the getResponseMessage function blocks until the request is finished being sent and the reply is received. Without ever checking the response value, your function just exits and the HTTP request might not be finished sending.
Thanks for this clarification.
I already tried with os.close() also tried with os.flush(). but same problem. :(
at last i have updated my code:
while ((bufferLength = bfis.read(buffer)) > 0) {
os.write(buffer, 0, bufferLength);
}
os.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
//logger
}
Now I am able to upload file.
Thanks again.

Java HttpURLConnection - POST with Cookie

I´m trying to send a post request with cookies. This is the code:
try {
String query = URLEncoder.encode("key", "UTF-8") + "=" + URLEncoder.encode("value", "UTF-8");
String cookies = "session_cookie=value";
URL url = new URL("https://myweb");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestProperty("Cookie", cookies);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(query);
out.flush();
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println(decodedString);
}
in.close();
// Send the request to the server
//conn.connect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The problem is the request is sent without the cookies. If I only make:
conn.connect(); and don´t send data, the cookies are sent OK.
I can´t check exactly what is happening, because the connection is thorugh SSL. I only check the response.
According to the URLConnection javadoc:
The following methods are used to access the header fields and the
contents AFTER the connection is made to the remote object:
* getContent
* getHeaderField
* getInputStream
* getOutputStream
Have you confirmed that in your test case above the request is getting to the server at all? I see you have the call to connect() after getOutputStream() and commented-out besides. What happens if you uncomment it and move up before the call to getOutputStream() ?

Categories

Resources