I've looked at multiple posts with this issue, and most/all of them have code that tries to create an inputstream before an outputstream. I get that. I didn't think I was doing that here. Where is my inputstream being created before the error?
URL url = new URL(myURL);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
// Grab, configure json input as myInput
// ...
byte[] input = myInput.getBytes();
conn.connect();
// Write as post body
try(OutputStream os = conn.getOutputStream()) {
os.write(input); // <-- java.net.ProtocolException Error "Cannot write output after reading input" here
}
// Attempt to read response using InputStream
// ...
From the documentation of URLConnection::connect()
Opens a communications link to the resource referenced by this URL, if such a connection has not already been established.
If the connect method is called when the connection has already been opened (indicated by the connected field having the value true), the call is ignored.
URLConnection objects go through two phases: first they are created, then they are connected. After being created, and before being connected, various options can be specified (e.g., doInput and UseCaches). After connecting, it is an error to try to set them. Operations that depend on being connected, like getContentLength, will implicitly perform the connection, if necessary
So basically you're requiring to write in the OutputStream after you have manually opened the connection to the resource, without taking care of which flags or settings are set on that process. That won't work.
Actually, you shouldn't even call the method connect() by yourself, since the methods that depend on being connected, like getInputStream() and getOutputStream() already will perform the connection if they need to.
Remove the line conn.connect().
Related
Consider the following code.
try {
httpURLConnection = (HttpURLConnection) new URL(strings[0]).openConnection();
httpURLConnection.setConnectTimeout(Config.HTTP_CONNECTION_TIMEOUT);
httpURLConnection.setReadTimeout(Config.HTTP_CONNECTION_TIMEOUT);
httpURLConnection.connect();
responseCode = httpURLConnection.getResponseCode();
httpURLConnection.getHeaderFields();
}
finally {
httpURLConnection.disconnect();
}
The issue is even when I don't use the InputStream to read the response, in my Internet/Wifi connection logs I can see the response-body. What I want is simply to check a field in the header and based upon that field I will continue reading the InputStream.
My questions are these:
Is it correct behavior for the connected stream to automatically download all/partial file even before a BufferedInputStream is created and read from?
If yes, then is it possible to stop the file download until an InputStream is used to read the response?
If not then is there something I am doing wrong or missing?
The response includes both the header and the body, the server does not stop for the client to acknowledge the headers before sending the body.
At the time the client is able to read the response code from the headers, a part of the body has already been sent, the size of which depends on the network latency, buffering, ....
The current implementation of HttpURLConnection.getResponseCode() even use getInputStream() to ensure that the connection is in the correct state.
The client can choose to ignore the body, but it's usually not recommended, because it may prevent a persistent connection to be reused.
I am not sure about Android but since Java 6, a background thread is automatically used to read the remaining data.
If If-Modified-Since is not an option, why not use a HEAD request ? :
The HTTP HEAD method requests the headers that are returned if the
specified resource would be requested with an HTTP GET method. Such a
request can be done before deciding to download a large resource to
save bandwidth, for example.
SocketAddress proxy = new InetSocketAddress("127.0.0.1", 8080);
URL url = new URL("http://192.168.1.1/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection(new Proxy(Proxy.Type.HTTP, proxy));
connection.setDoOutput(true);
String body = "This is a body example";
OutputStreamWriter writer = new OutputStreamWriter(new BufferedOutputStream(connection.getOutputStream()), "8859_1");
writer.write(body);
writer.flush();
writer.close();
connection.connect();
The problem is that when I run this code no requests are "catched" by my proxy (it is well configured). I know connect() is an abstract method in URLConnection but given that HttpURLConnection is extending URLConnection it is suppose to override it. This is what javadoc say about connect() : "Opens a communications link to the resource referenced by this URL, if such a connection has not already been established." So the request should have been sent. Anyone know what causes the problem?
NOTE : If I replace connection.connect() with connection.getResponseHeader() I catch a request. As I have read in javadoc if the connection is not set yet a call to getResponseHeader() will call implicitly the connect() method.
This is what javadoc say about connect() : "Opens a communications link to the resource referenced by this URL, if such a connection has not already been established."
Correct.
So the request should have been sent.
Non sequitur. Thwre is nothing in your quotation about sending the request.
As you have observed, the request is buffered until you perform some input step.
I requested to send some parameters from java file using post method. I did
String urlParameters = "param1=a¶m2=b¶m3=c";
URL url = new URL("http://testing/index.jsp");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
But from receiver's end asks me to send it in body instead of url parameter. I am not sure what I am doing wrong. Please explain me how this code will work and what changes has to be done if I want to send info in request body.
i believe you either need to call the connect() method on the URLConnection at the end, or call a method that would cause the connect to be called for you, like fetching the resulting input stream.
Also you should think about what format the body should be in. Often people like to use standard formats like json, but you will have to decide that between you and the people implementing the server.
I want to use HttpURLConnection to connect to my webservice, POST an XML and get a result. I am using the following code:
URL url = new URL(urlString);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
Problem is, when I call the setRequestProperty method, it fails with an IllegalStateException saying I am "already connected". Apparently, openConnection in fact opens the connection to the URL (in my debugger, I can see the connected boolean set to true). According to the URL documentation of Oracle though, it shouldn't. The Android docs are unclear about it.
How do I prevent openConnection to connect, so I can set extra properties?
Update it looks like the connection is in some pool and doesn't get disconnected, not even after calling connection.disconnect(), or even killing the server.
I do not think this is a duplicate of this question as it gives no real answer. Also, the documentation seems to be unclear.
openConnection() does not connect, and the code you have posted does not behave as yu have described. What opens the TCP connection is any of the following:
getInputStream()
getErrorStream()
getResponseCode()
Ergo you must have called one of those before trying to set a request property.
I use URL connection to download stream in the Internet. But after i reset the modem, i can't continue download this stream caz it error: Connection reset. How i solve it?
Here is my code:
URL url = new URL(_URL);
HttpURLConnection hUC = (HttpURLConnection) url.openConnection();
hUC.connect();
while (true) {
if ((_data.num = is.read(_data.b)) == -1) {
break;
}
//write to file
fos.write(_data.b, 0, _data.num);
}
You can't - at least, not how you may be expecting.
Instead, you need to handle your exception, and determine how much data you've already read. Once your Internet connection is re-established - assuming that the HTTP server you're downloading from supports requestable byte ranges - you can then set custom HTTP Headers on the request and re-download the remaining portions. (This will require a new HttpURLConnection.)
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 shows the related HTTP specifications involved to make this work.
This is a bit more complicated if you're looking for a "resume" type feature.
You would need to reissue the request once the internet comes back after a disconnect, and add a header to the request in order to resume the download at the byte number where you left off.
You need to set the Range property in the request header in order to specify how far in you're resuming. Then you would just continue to write to the "fos" object from there.
Check out this url: Java: resume Download in URLConnection