Fabian Fahrenholz Fabian Fahrenholz - 3 months ago 9
Apache Configuration Question

How to close apache's httpclient after Range request

I am building a download application to download movies from my server over HTTP using a Range request and apache's httpclient. I have no problems performing the request and handling the response but if I try to close the connection to the server (when closing the application) to resume the download later the connection remains open and continues downloading.

The whole Download is build in a Thread to handle multiple downloads at once.
I have a

private boolean running
to stop the thread to execute forever.

This is how I perform my request and handle the response data:

HttpGet req = new HttpGet(url.toString());

req.setHeader("If-Range", "Wed, 11 Jan 1984 08:00:00 GMT");
req.setHeader("Range", "bytes=" + (bytes_read+1) + "-");

HttpResponse res = client.execute(req);

if (res.getStatusLine().getStatusCode() == 206) {
ReadableByteChannel rbc = Channels.newChannel(res.getEntity().getContent());
FileChannel fc = new FileOutputStream(new File("test.mp4", false).getChannel();
int n;
ByteBuffer buffer = ByteBuffer.allocate(16*8192);
while((n = rbc.read(buffer)) > 0 && running){
buffer.flip();
fc.write(buffer);
buffer.clear();
}
}


This part of my code works fine as long as I do not try to interrupt the download.

But when I try to shutdown the download like this,

public void shutdown(){
running = false;
rbc.close();
fc.close();
client.close();
}


the execution of the shutdown method blocks at
rbc.close();
. I debugged this part of the code. The running flag did its job and causes the thread to come to an end.
But looking at the console you could see that after invoking the
close()
method the ReadableByteChannel it started to download the content from the connection and did nothing with it. It was not closing the connection but downloading till the end.

Now my question is: How can I stop the Channel to download the whole content from the Server before closing.

Closing the httpclient causes several Exceptions to be thrown.

Answer

I think the problem is the range request header you specify. It asks the sever to send all bytes starting from the specified byte number. Later in your code you to res.getEntity().getContent() which presumably reads all the data the server sends. I'd recommend only requesting certain chunks of data, e.g.

req.setHeader("Range", "bytes=" + (bytes_read+1) + "-" + (bytes_read+1 + CHUNCK_SIZE));

where you define CHUNK_SIZE to your liking. Then you can call this method repeatedly to read more bytes, if available.

Comments