2016-08-21 40 views
0

我正在構建一個下載應用程序,通過HTTP使用Range請求和apache的httpclient從我的服務器下載電影。我在執行請求和處理響應時沒有問題,但如果我嘗試關閉與服務器的連接(關閉應用程序時)以稍後恢復下載,則連接保持打開狀態並繼續下載。如何在範圍請求後關閉apache的httpclient

整個下載內置在一個線程中,一次處理多個下載。 我有一個private boolean running停止線程永久執行。

這是我執行我的要求和處理響應數據:

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(); 
    } 
} 

我的代碼這部分工作得很好,只要我不試圖中斷下載。

但是,當我嘗試關閉下載這個樣子,

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

關機方法塊在rbc.close();執行。我調試了這部分代碼。正在運行的標誌完成了它的工作並導致線程結束。 但看着控制檯,你可以看到,在調用close()方法ReadableByteChannel後,它開始從連接中下載內容,並且沒有做任何事情。它沒有關閉連接,而是下載到最後。

現在我的問題是:如何停止頻道在關閉之前從服務器下載整個內容。

關閉httpclient會導致引發多個異常。

回答

0

我認爲問題是您指定的範圍請求標題。它要求服務器從指定的字節數開始發送所有字節。後來在你的代碼中,你需要res.getEntity()。getContent(),它大概讀取服務器發送的所有數據。我建議只請求某些數據塊,例如

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

您可以根據自己的喜好定義CHUNK_SIZE。然後,您可以重複調用此方法以讀取更多字節(如果可用)。

+0

對於CHUNK_SIZE,你會推薦哪種尺碼? 10或20MB之間的東西? 我不想等待程序關閉緩慢連接的分鐘數 –

+0

這取決於連接速度有多快以及您願意等待多長時間。對我來說10或20 MB似乎是合理的。 – Guenther