java實現檔案的斷點續傳的下載
阿新 • • 發佈:2019-02-08
java的斷點續傳是基於之前java檔案下載基礎上的功能拓展
首先設定一個以執行緒ID為名的下載進度檔案,
每一次下載的進度會儲存在這個檔案中,下一次下載的時候,會根據進度檔案裡面的內容來判斷下載的進度。
package com.ldw.multilthreaddownload; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class Multidownload { static int ThreadCount = 3; //執行緒的個數 static int finishedThread = 0; //初始化下載完成的執行緒的個數 static String path = "http://192.168.0.102:8080/QQ.exe"; //確定下載地址 public static void main(String[] args) { // TODO Auto-generated method stub //傳送get請求,請求這個地址的資源 try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); if(conn.getResponseCode() == 200){ //獲取到請求資原始檔的長度 int length = conn.getContentLength(); File file = new File("QQ.exe"); //建立隨機儲存檔案 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); //設定臨時檔案的大小 raf.setLength(length); //關閉raf raf.close(); //計算出每一個執行緒下載多少位元組 int size = length / Multidownload.ThreadCount; for(int i = 0; i < Multidownload.ThreadCount; i ++){ //startIndex,endIndex分別代表執行緒的開始和結束位置 int startIndex = i * size; int endIndex = (i + 1) * size - 1; if(i == ThreadCount - 1){ //如果是最後一個執行緒,那麼結束位置寫死 endIndex = length -1; } //System.out.println("執行緒" + i + "的下載區間是" + startIndex + "到" + endIndex); new DownLoadThread(startIndex, endIndex, i).start(); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class DownLoadThread extends Thread{ int startIndex; int endIndex; int threadId; public DownLoadThread(int startIndex, int endIndex, int threadId) { super(); this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run(){ //使用http請求下載安裝包檔案 URL url; try { File fileProgress = new File(threadId + ".txt"); //判斷儲存下載進度的臨時檔案是否存在, if(fileProgress.exists()){ FileInputStream fis = new FileInputStream(fileProgress); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); //從下載進度的臨時檔案中讀取上一次下載的總進度,然後和原來文字的開始位置相加,得到新的下載位置 startIndex += Integer.parseInt(br.readLine()); fis.close(); } System.out.println("執行緒" + threadId + "下載區間是" + startIndex +"====" + endIndex); url = new URL(Multidownload.path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //設定請求資料的區間 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); //請求部分資料的響應碼是206 if(conn.getResponseCode() == 206){ //獲取一部分資料來讀取 InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; int total = 0; //拿到臨時檔案的引用 File file = new File("QQ.exe"); RandomAccessFile raf = new RandomAccessFile(file, "rwd"); //更新檔案的寫入位置,startIndex raf.seek(startIndex); while((len = is.read(b)) != -1 ){ //每次讀取流裡面的資料,同步吧資料寫入臨時檔案 raf.write(b, 0, len); total += len; //System.out.println("執行緒" + threadId + "下載了" + total); //生成一個專門記錄下載進度的臨時檔案 //File fileProgress = new File(threadId + ".txt"); RandomAccessFile fileProgressraf = new RandomAccessFile(fileProgress, "rwd"); //每一次讀取流裡面的資料以後,把當前執行緒下載的總進度寫入臨時檔案中 fileProgressraf.write((total + "").getBytes()); fileProgressraf.close(); } System.out.println("執行緒" + threadId + "下載過程結束==========================="); raf.close(); //三條執行緒下載完成以後,清理臨時檔案 Multidownload.finishedThread++; //執行緒安全 synchronized(Multidownload.path){ if(Multidownload.finishedThread == Multidownload.ThreadCount){ for(int i = 0; i < Multidownload.ThreadCount; i++){ File filefinish = new File(i + ".txt"); filefinish.delete(); } Multidownload.finishedThread = 0; } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }