Dev_Vikram
Dev_Vikram

Reputation: 121

How to set a timeout while reading from InputStream using httpurlconnection?

I have a java application in which I download files using HttpURLConnection. I set 15 Seconds in connect timeout and 1 hour in read timeout properties. As per my understanding, if file on server is big enough to take more than 1 hour to download, it will fail with timeout exception. Works fine. The problem is, when I pull the Internet cable out from the client machine while download is in progress(reading buffer from InputStream), the download process does not terminates immediately, it takes 1 hour (read timeout) to break the download. Is there any way I can terminate the download process? Following is the source code:

public class HttpDownloadUtility {
private static final int BUFFER_SIZE = 4096;
public static void downloadFile(String fileURL, String saveDir)
            throws IOException {
        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setConnectTimeout(15*1000);
        httpConn.setReadTimeout(60*60*1000);
        int responseCode = httpConn.getResponseCode();

        // always check HTTP response code first
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = "";
            String disposition = httpConn.getHeaderField("Content-Disposition");
            String contentType = httpConn.getContentType();
            int contentLength = httpConn.getContentLength();

            if (disposition != null) {
                // extracts file name from header field
                int index = disposition.indexOf("filename=");
                if (index > 0) {
                    fileName = disposition.substring(index + 10,
                            disposition.length() - 1);
                }
            } else {
                // extracts file name from URL
                fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
                        fileURL.length());
            }

            System.out.println("Content-Type = " + contentType);
            System.out.println("Content-Disposition = " + disposition);
            System.out.println("Content-Length = " + contentLength);
            System.out.println("fileName = " + fileName);

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream();
            String saveFilePath = saveDir + File.separator + fileName;

            // opens an output stream to save into file
            FileOutputStream outputStream = new FileOutputStream(saveFilePath);

            int bytesRead = -1;
            byte[] buffer = new byte[BUFFER_SIZE];
            while ((bytesRead = inputStream.read(buffer)) != -1) { //This is where the download gets stuck on some connection issues 
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();

            System.out.println("File downloaded");
        } else {
            System.out.println("No file to download. Server replied HTTP code: " + responseCode);
        }
        httpConn.disconnect();
    }
}

Upvotes: 4

Views: 4799

Answers (1)

user207421
user207421

Reputation: 310913

As per my understanding, if file on server is big enough to take more than 1 hour to download, it will fail with timeout exception.

No. If the server fails to respond to any single read request for over an hour, it will fail. The timeout starts when you call read(), and ends when a response to that read is received or the timeout period expires. Then it starts again next read. Total time has nothing to do with it. You've misunderstood completely.

Works fine.

Works fine but not as you described.

The problem is, when I pull the Internet cable out from the client machine while download is in progress(reading buffer from InputStream), the download process does not terminates immediately, it takes 1 hour (read timeout) to break the download.

That's exactly what it's supposed to do, as described above.

Is there any way I can terminate the download process?

Set a shorter timeout. Set it long enough so the server should respond within that interval, and short enough hat a cable pull doesn't take too long to time out. An hour is too long. Try a few minutes.

Upvotes: 2

Related Questions