Java 實現的斷點下載

來源:互聯網
上載者:User

標籤:下載工具   java ee   迅雷   網路   瀏覽器   

該斷點下載可應用於瀏覽器或者迅雷等下載工具的下載,實現方式有多種多樣的,本文只研究了單線程的下載,迅雷等下載工具會自動將下載資源分塊並記錄每塊的起始位置,然後根據系統效能,起多線程下載。

1. 基本原理

從Request Header的Range資訊裡面擷取已經下載的檔案大小,然後建立response的outputstream 向用戶端(瀏覽器或者迅雷等下載工具)寫,寫的時候又利用header裡面的“Content-Range”, 讓用戶端知道從哪個位置開始寫;

讀取網路資源方面,利用HttpClient類比request請求,發起post或者get請求,只是這個請求跟一般請求有點不一樣:需要帶上Range資訊,告訴程式該從哪個位置開始讀資料。

2. 需要使用的Java 組件

  • HttpServletRequest / Response
  • HttpClient
  • ServletOutputStream
  • BufferedInputStream

3. 代碼實現

/** * @desc 斷點下載工具方法 * @param request * @param response * @param fileLength * @param contentType * @param fileName * @param fileId */public static void resumeDownload(HttpServletRequest request,HttpServletResponse response, Long fileLength, String contentType,String fileName, String fileId) {ServletOutputStream out = null;response.reset();// 記錄斷點續傳的開始點long pos = 0;if (null != request.getHeader("Range")) {response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);try {pos = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-.*", ""));} catch (NumberFormatException e) {LOGGER.error(e.getMessage(), e);pos = 0;}String contentRange = new StringBuffer("bytes ").append(pos + "").append("-").append((fileLength.intValue() - 1) + "").append("/").append(fileLength.intValue() + "").toString();response.setHeader("Content-Range", contentRange);}response.setHeader("Accept-Ranges", "bytes");response.setHeader("Content-Length",String.valueOf(fileLength.intValue() - pos));response.setCharacterEncoding("UTF-8");response.setContentType(contentType);response.setHeader("Content-disposition", "attachment;filename=\""+ fileName + "\"");try {out = response.getOutputStream();} catch (IOException e) {LOGGER.error(e.getMessage(), e);}// 斷點下載CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost(SysConf.getString("fezo.download.url"));List<NameValuePair> nvps = new ArrayList<NameValuePair>();nvps.add(new BasicNameValuePair(SysConf.getString("fezo.download.param"), fileId));HttpResponse httpResponse = null;BufferedInputStream input = null;try {httpPost.setEntity(new UrlEncodedFormEntity(nvps));httpPost.setHeader("Range", "bytes=" + pos + "-");httpResponse = httpClient.execute(httpPost);input = new BufferedInputStream(httpResponse.getEntity().getContent());byte[] buffer = new byte[CommonConstants.BUFFER_SIZE];int len = -1;while ((len = input.read(buffer)) != -1) {out.write(buffer, 0, len);}out.flush();out.close();input.close();} catch (UnsupportedEncodingException e) {LOGGER.error(e.getMessage(), e);} catch (ClientProtocolException e) {LOGGER.error(e.getMessage(), e);} catch (IOException e) {// 可以忽略這個異常,有可能是使用者暫停下載,或者迅雷等下載工具分塊下載} finally {try {if (httpClient != null) httpClient.close();} catch(IOException e) {LOGGER.error(e.getMessage(), e);}}}

4. 重點與痛點

    - 擷取response的輸出資料流程來向用戶端提供下載功能,而不是簡單的把資料寫入到某個具體的檔案,核心代碼:out = response.getOutputStream();

    - 頭資訊裡面"Range" 和 "Conent-Range" 等資訊的處理;

    - 迅雷等多線程分塊下載用戶端下載的處理:還是要處理好"Range" 和 "Conent-Range" 等頭部資訊,迅雷會自動將檔案內容分塊、記錄起始位置。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Java 實現的斷點下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.