dddew dddew - 2 months ago 14
Java Question

Read an InputStream from a URL and Write to HttpServletResponse without creating a temp file

I tried to read an InputStream from a URL and write to HttpServletResponse directly without creating a temporary file in an HttpServlet, but failed to get real Content-Length of the file. I've been told that I can't determine the amount of data in a stream without reading it. Can someone help me? I'd really appreciate it.

Answer

Since you are reading from a URL, you should have the length available from the Content-length header of that URL.

HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.connect();
if ( connection.getResponseCode() == 200 ) {
    int contentLength = connection.getContentLength();
    response.setContentLength( contentLength );

Note that you should not use inputStream.available(). The available() method merely tells you how many bytes can be read without blocking (that is, waiting for the next chunk to arrive from the network). It does not tell you the size of the stream! But in an HttpURLConnection, you can get the value of the content-length header using the getContentLength() method.

Once you do that, you can start a read-write loop to copy all the data, e.g.

InputStream source = connection.getInputStream();
OutputStream target = response.getOutputStream();

int FILE_CHUNK_SIZE = 1024 * 4;
byte[] chunk = new byte[FILE_CHUNK_SIZE]; 
int n =0;
while ( (n = source.read(chunk)) != -1 ) {
    target.write(chunk, 0, n);
}

Remember to use try-catch around all this, as there can be many kinds of exceptions thrown in such a transaction. And when you catch the exception, remember to set a response code in your response, which is not 200.

Comments