Amit
Amit

Reputation: 34745

Java - Utility method to pass a url and get its InputStream

I wanted to write a Utility function something like this

public static InputStream getInputStream(URL url) {...}

so that I can use that InputStream according to my usage.

e.g.

If want to download a song, then I can directly write bytes from the InputStream to a file without converting bytes ->> String -->> file

OR

If I want to read some text from the url, then I can convert the InputStream to String.

Problem:

  1. When I am using this InputStream in my caller function, I am getting the following exception

    java.net.SocketException: Socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:204)
    at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:182)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.Reader.read(Reader.java:140)
    at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2001)
    at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1980)
    at org.apache.commons.io.IOUtils.copy(IOUtils.java:1957)
    at org.apache.commons.io.IOUtils.copy(IOUtils.java:1907)
    at org.apache.commons.io.IOUtils.toString(IOUtils.java:778)
    at org.apache.commons.io.IOUtils.toString(IOUtils.java:803)    
    at hungama.HungamaContentDownloader.downloadContent(HungamaContentDownloader.java:87)
    at hungama.HungamaContentDownloader.main(HungamaContentDownloader.java:46)
    
  2. Let's say even If I am able successfully read the content from the InputStream, How can I close the HttpConnection that I created inside this utility function? If I close it before returning, then the InputStream won't work. And If I don't close it before returning from the utility function, then the connection will remain unclosed.

Note: I don't want to return byte [] or String from the utility function because in some cases the data might be very large because of which I can't store the whole data in memory before operating on that data.

Code:

public static InputStream getRemoteHttpResource(String url, String username, String password, int timeout) {
    if(url == null)
        return null;

    DefaultHttpClient client = null;
    HttpGet request = null;
    try {
        client = new DefaultHttpClient();
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);

        request = new HttpGet(url);
        request.setHeader("Accept-Language", "en-US,en;q=0.8");

        HttpResponse response = client.execute(request);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == 200)
            return response.getEntity().getContent();
        else
            logger.warn("Error response : " + statusLine + ". For : " + url + ". Response: " + response);
    }
    catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
        if(request != null)
            request.releaseConnection();
        if (client != null)
            client.getConnectionManager().shutdown();
    }

    return null;
}

Note: I am using org.apache.http.impl.client.DefaultHttpClient

Upvotes: 1

Views: 1591

Answers (2)

Henry
Henry

Reputation: 43738

You could return your own implementation of InputStream that wraps the InputStream of the connection and override the close method. A FilterInputStream would already do most of the job, as it delegates the operations to the enclosed InputStream.

Upvotes: 3

ug_
ug_

Reputation: 11440

What you could do:

void pipRemoteHttpResource(String url, String username, String password, int timeout, OutputStream out) {
    .. same code ..
    if (statusLine.getStatusCode() == 200)
        pipeStreams(response.getEntity().getContent(), out);
    .. same code ..
}


// writes input to output
public static void pipeStreams(java.io.InputStream source, java.io.OutputStream destination) throws IOException {

    // 16kb buffer
    byte [] buffer = new byte[16 * 1024];
    int read = 0;
    while((read=source.read(buffer)) != -1) {
        destination.write(buffer, 0, read);
    }
    destination.flush();
    destination.close();
    source.close();
}

Upvotes: 1

Related Questions