I am using Jsoup Java HTML parser to fetch images from a particular URL. But some of the images are throwing a status 502 error code and are not saved to my machine. Here is the code snapshot i have used:-
String url = "http://www.jabong.com";
String html = Jsoup.connect(url.toString()).get().html();
Document doc = Jsoup.parse(html, url);
images = doc.select("img");
for (Element element : images) {
String imgSrc = element.attr("abs:src");
log.info(imgSrc);
if (imgSrc != "") {
saveFromUrl(imgSrc, dirPath+"/" + nameCounter + ".jpg");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
log.error("error in sleeping");
}
nameCounter++;
}
}
And the saveFromURL function looks like this:-
public static void saveFromUrl(String Url, String destinationFile) {
try {
URL url = new URL(Url);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destinationFile);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
} catch (IOException e) {
log.error("Error in saving file from url:" + Url);
//e.printStackTrace();
}
}
I searched on internet about status code 502 but it says error is due to bad gateway. I don't understand this. One of the possible things i am thinking that this error may be because of I am sending get request to images in loop. May be webserver is not able handle to this much load so denying the request to the images when previous image is not sent.So I tried to put sleep after fetching every image but no luck :(
Some advices please
Here's a full code example that works for me...
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
public class DownloadImage {
public static void main(String[] args) {
// URLs for Images we wish to download
String[] urls = {
"http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png",
"http://www.google.co.uk/images/srpr/logo3w.png",
"http://i.microsoft.com/global/en-us/homepage/PublishingImages/sprites/microsoft_gray.png"
};
for(int i = 0; i < urls.length; i++) {
downloadFromUrl(urls[i]);
}
}
/*
Extract the file name from the URL
*/
private static String getOutputFileName(URL url) {
String[] urlParts = url.getPath().split("/");
return "c:/temp/" + urlParts[urlParts.length-1];
}
/*
Assumes there is no Proxy server involved.
*/
private static void downloadFromUrl(String urlString) {
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlString);
System.out.println("Reading..." + url);
HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy);
is = conn.getInputStream();
String filename = getOutputFileName(url);
fos = new FileOutputStream(filename);
byte[] readData = new byte[1024];
int i = is.read(readData);
while(i != -1) {
fos.write(readData, 0, i);
i = is.read(readData);
}
System.out.println("Created file: " + filename);
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if(is != null) {
try {
is.close();
} catch (IOException e) {
System.out.println("Big problems if InputStream cannot be closed");
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
System.out.println("Big problems if FileOutputSream cannot be closed");
}
}
}
System.out.println("Completed");
}
}
You should see the following ouput on your console...
Reading...http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png
Created file: c:/temp/apple-touch-icon.png
Completed
Reading...http://www.google.co.uk/images/srpr/logo3w.png
Created file: c:/temp/logo3w.png
Completed
Reading...http://i.microsoft.com/global/en-us/homepage/PublishingImages/sprites/microsoft_gray.png
Created file: c:/temp/microsoft_gray.png
Completed
So that's a working example without a Proxy server involved.
Only if you require authentication with a proxy server here's an additional Class that you'll need based on this Oracle technote
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class ProxyAuthenticator extends Authenticator {
private String userName, password;
public ProxyAuthenticator(String userName, String password) {
this.userName = userName;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password.toCharArray());
}
}
And to use this new Class you would use the following code in place of the call to openConnection() shown above
...
try {
URL url = new URL(urlString);
System.out.println("Reading..." + url);
Authenticator.setDefault(new ProxyAuthenticator("username", "password");
SocketAddress addr = new InetSocketAddress("proxy.server.com", 80);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy);
...
Your problem sounds like HTTP communication issues, so you are probably better off trying to use a library to handle the communication side of things. Take a look at Apache Commons HttpClient.
Some notes about your code example. You haven't used a URLConnection object so it's not clear what the behaviour will be in regards to the Web/Proxy servers and closing resources cleanly, etc. The HttpCommon library mentioned will help in this aspect.
There also seems to be some examples of doing what you want using J2ME libararies. Not something I have used personally but may also help you out.
Related
I'm kind of new to Android and I have a task to open a TCP socket and listen to a specific port.
A client application is supposed to send me 2 images and a string that are related to each other so instead of sending each data alone we thought about putting all data in a json object and send this object.
My question is, how do I parse this json into saving 2 images and a string?
So this json is supposed to be like this:
data
{
FileName: "some string",
Image1: "Image encoded with encode base64",
Image2: "Image encoded with encode base64"
}
I'm using an AsyncTask so here is the code where I get the socket data:
public class DataRecord
{
String Image1;
String Image2;
String FileName;
}
protected DataRecord doInBackground(Socket... sockets) {
DataRecord dataRecord = null;
if (isExternalStorageWritable() && sockets.length > 0) {
Socket socket = sockets[0];
dataRecord = socket.getOutputStream(); // how to extract the data from the socket into this object ???
File file = new File(Environment.getExternalStorageDirectory(), dataRecord.FileName);
byte[] bytes = new byte[(int) file.length()];
BufferedInputStream inputStream;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
inputStream.read(bytes, 0, bytes.length);
OutputStream outputStream = dataRecord.Image1;
outputStream.write(bytes, 0, bytes.length);
outputStream.flush();
socket.close();
}
catch (Exception e) { }
finally {
try {
socket.close();
} catch (IOException e) { }
}
}
return dataRecord;
}
And I need to get it from the socket object and extract an object from it to save the 2 images to the SD card and extract the string to the UI.
I know this question probably have more than one answer, but still posting an answer is a good idea.
So, I found this link here A Simple Java TCP Server and TCP Client which helped me getting started with my solution.
I've also used Gson to parse my JSON string using this nice tutorial: Android JSON Parsing with Gson Tutorial.
Finally, my code looks like this:
ServerSockerThread.java - this is the java class for the listening server which waits for incoming files:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketThread extends Thread {
static final int SocketServerPORT = 6789;
ServerSocket serverSocket;
#Override
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SocketServerPORT);
while (true) {
socket = serverSocket.accept();
new FileSaveThread().execute(socket);
}
}
catch (IOException e) { }
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) { }
}
}
}
protected void onDestroy() {
if (serverSocket != null) {
try {
serverSocket.close();
}
catch (IOException e) { }
}
}
}
FileSaveThread.java - this is the java class that is being called by the above server class for each incoming file:
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Base64;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.Socket;
public class FileSaveThread extends AsyncTask<Socket, Void, DataRecord> {
#Override
protected void onPostExecute(DataRecord dataRecord) {
super.onPostExecute(dataRecord);
}
#Override
protected DataRecord doInBackground(Socket... sockets) {
DataRecord dataRecord = null;
if (isExternalStorageWritable() && sockets.length > 0) {
Socket socket = sockets[0];
try {
Gson gson = new Gson();
Reader reader = new InputStreamReader(socket.getInputStream());
SocketObject socketObject = gson.fromJson(reader, SocketObject.class);
SaveFileToSDCard(socketObject.Image1, "Image1.png");
SaveFileToSDCard(socketObject.Image2, "Image2.png");
SaveFileToSDCard(socketObject.Image3, "Image3.png");
dataRecord = new DataRecord(socketObject.Name);
}
catch (Exception e) { }
finally {
try {
socket.close();
} catch (IOException e) { }
}
}
return dataRecord;
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
private void SaveFileToSDCard(String base64String, String fileName) throws IOException {
byte[] decodedString = Base64.decode(base64String.getBytes(), android.util.Base64.DEFAULT);
File file = new File(Environment.getExternalStorageDirectory(), fileName);
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
fileOutputStream.write(decodedString);
fileOutputStream.close();
fileOutputStream.flush();
}
}
I am trying to use an API from https://us.mc-api.net/ for a project and I have made this as a test.
public static void main(String[] args){
try {
URL url = new URL("http://us.mc-api.net/v3/uuid/193nonaxishsl/csv/");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
System.out.println("I/O Error");
}
}
}
And this is giving me an IOException error but when ever I open the same page in my web browser I get
false,Unknown-Username
which is what I want to get from the code. I am new and don't really know why it is happening or why.
EDIT: StackTrace
java.io.FileNotFoundException: http://us.mc-api.net/v3/uuid/193nonaxishsl/csv/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at com.theman1928.Test.Main.main(Main.java:13)
The URL is returning status code 404 and therefore the input stream (mild guess here) is not being created and therefore is null. Sort the status code and you should be OK.
Ran it with this CSV and it is fine: other csv
If the error code is important to you then you can use HttpURLConnection:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
System.out.println("code:"+conn.getResponseCode());
In that way you can process the response code before proceeding with a quick if-then-else check.
I tried it with the Apache HTTP libraries. The API endpoint seems to return a status code of 404, hence your error. Code I used is below.
public static void main(String[] args) throws URISyntaxException, ClientProtocolException, IOException {
HttpClient httpclient = HttpClients.createDefault();
URIBuilder builder = new URIBuilder("http://us.mc-api.net/v3/uuid/193nonaxishsl/csv/");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
HttpResponse response = httpclient.execute(request);
System.out.println(response.getStatusLine().getStatusCode()); // 404
}
Switching out the http://us.mc-api.net/v3/uuid/193nonaxishsl/csv/ with www.example.com or whatever returns a status code of 200, which further proves an error with the API endpoint. You can take a look at [Apache HTTP Components] library here.
This has to do with how the wire protocols are working in comparison with the java.net classes and an actual browser. A browser is going to be much more sophisticated than the simple java.net API you are using.
If you want to get the equivalent response value in Java, then you need to use a richer HTTP API.
This code will give you the same response as the browser; however, you need to download the Apache HttpComponents jars
The code:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.HttpClients;
public class TestDriver
{
public static void main(String[] args)
{
try
{
String url = "http://us.mc-api.net/v3/uuid/193nonaxishsl/csv";
HttpGet httpGet = new HttpGet(url);
getResponseFromHTTPReq(httpGet, url);
}
catch (Throwable e)
{
e.printStackTrace();
}
}
private static String getResponseFromHTTPReq(HttpUriRequest httpReq, String url)
{
HttpClient httpclient = HttpClients.createDefault();
// Execute and get the response.
HttpResponse response = null;
HttpEntity entity = null;
try
{
response = httpclient.execute(httpReq);
entity = response.getEntity();
}
catch (IOException ioe)
{
throw new RuntimeException(ioe);
}
if (entity == null)
{
String errMsg = "No response entity back from " + url;
throw new RuntimeException(errMsg);
}
String returnRes = null;
InputStream is = null;
BufferedReader buf = null;
try
{
is = entity.getContent();
buf = new BufferedReader(new InputStreamReader(is, "UTF-8"));
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
StringBuilder sb = new StringBuilder();
String s = null;
while (true)
{
s = buf.readLine();
if (s == null || s.length() == 0)
{
break;
}
sb.append(s);
}
returnRes = sb.toString();
System.out.println("Response: [" + returnRes + "]");
}
catch (UnsupportedOperationException | IOException e)
{
throw new RuntimeException(e);
}
finally
{
if (buf != null)
{
try
{
buf.close();
}
catch (IOException e)
{
}
}
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
}
}
}
return returnRes;
}
}
Outputs:
Response Code : 404
Response: [false,Unknown-Username]
Hi I am using following code to reading URL:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class JavaHttpUrlConnectionReader
{
public static void main(String[] args)
throws Exception
{
new JavaHttpUrlConnectionReader();
}
public JavaHttpUrlConnectionReader()
{
try
{
String myUrl = "http://epaperbeta.timesofindia.com/NasData/PUBLICATIONS/THETIMESOFINDIA/Delhi/2015/06/09/PageIndex/09_06_2015.xml";
// if your url can contain weird characters you will want to
// encode it here, something like this:
// myUrl = URLEncoder.encode(myUrl, "UTF-8");
String results = doHttpUrlConnectionAction(myUrl);
System.out.println(results);
}
catch (Exception e)
{
// deal with the exception in your "controller"
}
}
/**
* Returns the output from the given URL.
*/
private String doHttpUrlConnectionAction(String desiredUrl)
throws Exception
{
URL url = null;
BufferedReader reader = null;
StringBuilder stringBuilder;
try
{
// create the HttpURLConnection
url = new URL(desiredUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// just want to do an HTTP GET here
connection.setRequestMethod("GET");
// uncomment this if you want to write output to this url
//connection.setDoOutput(true);
// give it 15 seconds to respond
connection.setReadTimeout(35*1000);
connection.connect();
// read the output from the server
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
stringBuilder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
stringBuilder.append(line + "\n");
}
return stringBuilder.toString();
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
finally
{
// close the reader; this can throw an exception too, so
// wrap it in another try/catch block.
if (reader != null)
{
try
{
reader.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
}
It gives me following error:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:687)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:632)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1072)
at JavaHttpUrlConnectionReader.doHttpUrlConnectionAction(JavaHttpUrlConnectionReader.java:77)
at JavaHttpUrlConnectionReader.<init>(JavaHttpUrlConnectionReader.java:33)
at JavaHttpUrlConnectionReader.main(JavaHttpUrlConnectionReader.java:21)
Kindly tell me the reason why it occurs, and solution for it.
When I run this code outside of my office LAN, it is working fine. but not in office LAN.
Thanks & Regards
Abhishek
Your URL:
http://epaperbeta.timesofindia.com/NasData/PUBLICATIONS/THETIMESOFINDIA/Delhi/2015/06/09/PageIndex/09_06_2015.xml
is not accessible without a proxy (for example I can't access it from here), no wonder why cannot be read from the stream.
Check your proxy settings. you could try the url in the browser with/without proxy and see the difference.
As #Jens commented look at this.
I'm trying to implement async http in java. Here is the important
part of the code:
for (String urlString : urls)
{
// TODO: try and get rid of these two heap allocations
url = new URL(urlString);
request = new HTTPRequest(url);
request.addHeader(userAgentHeader);
request.addHeader(authorizationHeader);
request.addHeader(acceptEncodingHeader);
request.addHeader(acceptCharsetHeader);
responses.add(URLFetchServiceFactory.getURLFetchService().fetchAsync(reques t));
apiCallsMade++;
}
for (Future<HTTPResponse> futureResponse : responses)
{
parseResponse(new String(futureResponse.get().getContent()));
}
I keep getting this error:
com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'urlfetch' or call 'Fetch()'
was not found.
I looked around for any jars that were missing from
the classpath but didn't see anything missing. Do you know which jar
that code is in? I googled the error and also searched through this
group but found nothing.
Thanks,
David
With Google appengine, you cannot use those api's in the local java applications. This will work only when you develop and deploy web application using google appengine sdk. This is designed to work this way only.
When you use this api, it will make use of http client and in case of app engine environment, it will make use of google infrastructure. If you still want to unit test the application designed for google appengine you might consider using LocalURLServiceFactory.
here's a simple working example of how to do this that I created for my blog:
package org.appEngineAsync.server;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import org.appEngineAsync.client.GreetingService;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService
{
private HTTPRequest request = null;
HTTPHeader acceptCharsetHeader = new HTTPHeader("Accept-Charset", "utf-8");
// All three of these data types are synchronized for thread safety
List<Future<HTTPResponse>> responses = new CopyOnWriteArrayList<Future<HTTPResponse>>();
protected List<String> tempSingleUrl = new CopyOnWriteArrayList<String>();
StringBuffer sb = new StringBuffer();
public String greetServer(String input) throws Exception
{
List<String> urlsToFetchInParrallel = new ArrayList<String>();
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=1&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=11&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=21&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=31&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=41&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=51&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=61&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=71&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=81&max-results=10&v=2");
urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=91&max-results=10&v=2");
return performHttpRequest(urlsToFetchInParrallel);
}
// pass in 10 urls at a time
private final String performHttpRequest(List<String> urls) throws NumberFormatException, Exception
{
URL url = null;
request = null;
byte[] tempBuffer = null;
byte[] buffer = null;
ByteArrayInputStream memoryStream = null;
ByteArrayOutputStream baos = null;
final int buffSize = 8192;
int size = 0;
sb.setLength(0);
responses.clear();
try
{
for (String urlString : urls)
{
url = new URL(urlString);
request = new HTTPRequest(url);
request.addHeader(acceptCharsetHeader);
responses.add(URLFetchServiceFactory.getURLFetchService().fetchAsync(request));
}
for (Future<HTTPResponse> futureResponse : responses)
{
try
{
memoryStream = new ByteArrayInputStream(futureResponse.get().getContent());
tempBuffer = new byte[buffSize];
baos = new ByteArrayOutputStream();
while ((size = memoryStream.read(tempBuffer, 0, buffSize)) != -1)
{
baos.write(tempBuffer, 0, size);
}
buffer = baos.toByteArray();
} catch (Exception ex)
{
// TODO: log or take other action
return null;
} finally
{
try
{
baos.close();
} catch (Exception ex)
{
// TODO: log
}
}
// TODO: put this on one line when done debugging
String responseString = new String(buffer, "UTF-8");
sb.append(responseString);
}
// TODO: put this on one line when done debugging
String allResponsesString = sb.toString();
return allResponsesString;
} catch (Exception ex)
{
// TODO: log
return null;
} finally
{
try
{
request = null;
url = null;
memoryStream = null;
tempBuffer = null;
baos = null;
} catch (Exception ex)
{
// TODO: log
return null;
}
}
}
}
My only guess is that it's due to a Future not completing before attempting to access its response. But that's a complete and utter guess!
Maybe check each of the futureResponses .isDone() and .isCancelled() before accessing its .get().
I try to create the simplest Simplest WebServer and Client using HTTP. (Please, don't tell me to using Apache HTTPClient).
Client: try to PUT some file to Server.
// **PUT**
if(REQUEST.toUpperCase().equals("PUT")) {
File sourceFile = new File(fileName);
if(!sourceFile.canRead()) {
System.out.println("Have not access to this file...");
return;
}
try {
BufferedInputStream is = new BufferedInputStream(new FileInputStream(sourceFile));
URL url = new URL("http://" + HOST+":"+PORT);
System.setProperty("http.keepAlive", "true");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "Application/octet-stream");
connection.setRequestProperty("Content-Length",Long.toString(sourceFile.length()));
connection.addRequestProperty("Content-disposition","attachment; filename="+fileName);
BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());
byte[] buf = new byte[sizeArr];
int r = 1;
while((r = is.read(buf)) > 0) {
os.write(buf, 0, r);
}
os.flush();
os.close();
System.out.println("Waiting for the response...");//this is written to console
System.out.println(connection.getResponseCode());//HERE infinite waiting
is.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
On Server: if Request == PUT, then:
// **PUT**
if (header.toUpperCase().equals("PUT")) {
System.setProperty("http.keepAlive", "true");
String fileName = null;
if((fileName = extract(request.toUpperCase(),"FILENAME=","\n")) == null) {
fileName = "UnknownFile.out";
}
try {
File sourceFile = new File(fileName);
BufferedOutputStream osFile = new BufferedOutputStream
(new FileOutputStream(sourceFile));
byte[] locbuf = new byte[sizeArr];
int locr = 1;
while((locr = is.read(locbuf)) > 0) {
System.out.println("locr= "+locr);//this is written to console
osFile.write(locbuf, 0, locr);
}
System.out.println("Ending to record the data to the file.");
// this is NOT written to console
osFile.flush();
osFile.close();
}
catch(IOException ex) {
os.write(CodeRequest("500 Internal Server Error").getBytes());
os.close();
ex.printStackTrace();
return;
}
System.out.println("Trying to send 200 OK");
os.write(CodeRequest("200 OK").getBytes());
os.flush();
os.close(); // where os = clientSocket.getOutputStream();
}
Why doesn't the Client get a Response from the Server? If I interrupted the Client's infinite loop, then WebServer would correctly record data to file. But Client will never know that his file was normally uploaded to the server. If I comment out this statement on Client:
// System.out.println(connection.getResponseCode());
Then Client correctly exit from loop and ends. But Server doesn't even write to console this:
while((locr = is.read(locbuf)) > 0) {
System.out.println("locr= "+locr);//this is NOT written to console
osFile.write(locbuf, 0, locr);
}
Server ONLY writes this to console this:
localExcString index out of range: -1
without any Error message.
What's wrong?
Your example code for the server doesn't show the declaration and initialisation of 'is'.
However, my guess is that since the session is keep alive the call to is.read() will block until some data arrives. You have set the content length in the client, so I would be expecting to see the read loop complete when that amount of data has been successfully read.
What string is the CodeRequest method returning in the server code? I think that the problem may be that you are not putting a CRLF at the end of the status line and another one at the end of the response header. For details, read the HTTP 1.1 specification.
You need to call URLConnection#getInputStream() after the write to actually send the request (and thus retrieve the response). Only after this point you can request the response status. This is implemented so because it might take longer to build the request body than to actually sending it and also because there's actually no point of having a request if you're not interested in the response.
Edit sorry, I was wrong. The getResponseCode() already implicitly calls getInputStream().
Anyway, I created a small testcase (see SSCCE for more info) and it just works fine. Try it and see if it works in your case as well.
Client:
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class Test {
public static void main(String[] args) throws Exception {
String data = "Hello!";
URL url = new URL("http://localhost:8080/playground/test");
OutputStream output = null;
try {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
output = connection.getOutputStream();
output.write(data.getBytes());
System.out.println("Response code: " + connection.getResponseCode());
} finally {
if (output != null) try { output.close(); } catch (IOException ignore) {}
}
}
}
Server:
package mypackage;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Test extends HttpServlet {
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
InputStream input = null;
try {
input = request.getInputStream();
int data;
while ((data = input.read()) > -1) {
System.out.write(data);
}
System.out.println();
} finally {
if (input != null) try { input.close(); } catch (IOException ignore) {}
}
}
}
Result should be a Response code: 200 in the client's stdout and a Hello! in the server's stdout.
Hope this helps in pinpointing the cause of your problem.
On Server:
String strFileLen = extract(request.toUpperCase().trim(),"CONTENT-LENGTH:","\n");
long fileLength = 0;
if(strFileLen != null) {
fileLength = Long.parseLong(strFileLen.trim());
System.out.println("fileLength= "+fileLength);
};
byte[] locbuf = new byte[sizeArr];
int locr = 1;long sumLen = 0;
if(fileLength != 0) {
while((sumLen += (locr=is.read(locbuf))) != fileLength) {
System.out.println("sumLen= "+sumLen);
osFile.write(locbuf, 0, locr);
}
}
===================================================
This works well.