1. 程式人生 > 其它 >斷點續傳(大檔案的下載)後臺功能實現

斷點續傳(大檔案的下載)後臺功能實現

某網盤

  • 可以隨時暫停、啟動
  • 多工
  • 下載過程中、由於某一些特殊原因(宕機、斷電、斷網等),導致檔案下載失敗
    • 再一次下載的時候,還可以繼續在原來的基礎上下載
    • 當上一次下載的20%,再一次下載的時候,從20%繼續下載
  • 本地都會產生一個臨時資料檔案
    • 中斷後,檔案不會消失

斷點續傳

原理:

實現:

長連線:socket、urlconnection、http、okhttp、httpclient

思路:

  • 指定URL
  • 建立一個目錄(指定臨時檔案)
  • 從伺服器中獲取物件流
  • 告訴伺服器從哪個位置下標,開始傳送資料
  • 將物件流物件,寫入到臨時檔案中
  • 根據讀取到的物件流長度來進行定義
  • 如果長度有值,則進行寫入
  • 如果長度=-1,則無需進行寫入操作

程式碼:

/**
 *
 * @author: likang
 * @date: 2019/12/5 20:44
 * @description: 斷點續傳(仿百度網盤下載功能)
 */
public class FileDownLoadUtils {

    public static void main(String[] args) {
        //指定URL
        String url = "http://mirrors.aliyun.com/centos/8.0.1905/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso";
        
//下載檔案 downLoadFile(url); } /* * @Description: 建立檔案 * @author: likang * @date: 2019/12/5 20:47 * @params: [url] * @return: void * @exception: */ private static void downLoadFile(String url) { //指定本地下載的目錄地址 File file = new File(FileDownLoadUtils.class
.getResource("").getFile()); // //生成一個臨時檔案(目的:主要是記錄資料的下標位置(位元組長度)) // //getAbsolutePath:獲取絕對路徑 // //separator:自動識別當前系統資源分割符合 file = new File(file.getAbsolutePath() + File.separator + "CentOS-8-x86_64-1905-dvd1.iso.bak"); //如果目錄不存在,則建立 if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } //將url中的資料流物件,寫入到臨時檔案中file writeFile(url,file); } /* * @Description: 通過url獲取伺服器物件流,並寫入到檔案中file * @author: likang * @date: 2019/12/5 21:00 * @params: [url, file] * @return: void * @exception: */ private static void writeFile(String url, File file) { byte[] bytes = new byte[1024*1024]; //定義流物件 InputStream inputStream = null;//資料流 FileOutputStream fileOutputStream = null;//寫入file物件資料流 long fileLength = 0; int byteCount = 0; //根據URL和伺服器建立連線---資料流 try { fileOutputStream = new FileOutputStream(file, true); fileLength = file.length(); //建立連線,獲取物件流 inputStream = getInputStream(url,fileLength); // byteCount = inputStream.read(bytes); // while(byteCount != -1){ // //資料流---file檔案中(臨時檔案) // fileOutputStream.write(bytes, 0, byteCount); // } while((byteCount = inputStream.read(bytes)) != -1){ //資料流---file檔案中(臨時檔案) fileOutputStream.write(bytes, 0, byteCount); } } catch (Exception e) { e.printStackTrace(); }finally { //關閉流物件 try { inputStream.close(); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /* * @Description: 建立連線、獲取物件流 * @author: likang * @date: 2019/12/5 21:18 * @params: [url, fileLength] * @return: java.io.InputStream * @exception: */ private static InputStream getInputStream(String url, long startFileLength) { InputStream inputStream = null; HttpURLConnection connection; try { URL filePath = new URL(url);//和伺服器建立連線、獲取檔案路徑 connection = (HttpURLConnection) filePath.openConnection();//開啟連線 connection.setConnectTimeout(3*1000);//連線超時時間 long lengthLong = connection.getContentLengthLong();//檔案的總長度 if(startFileLength < lengthLong){//還沒下載完畢 connection.disconnect();//銷燬連結 connection = (HttpURLConnection) filePath.openConnection();//開啟連線 connection.setConnectTimeout(3*1000);//連線超時時間 connection.setRequestProperty("RANGE", "bytes=" + startFileLength + "-");//設定請求傳送下標的物件 System.out.println(connection.getContentLengthLong()); inputStream = connection.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return inputStream; } }