java多線程下載文件和斷點下載

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.print.attribute.standard.Finishings;

public class MultiDownload {

    static int ThreadCount = 3;       //表明3個進程
    static int finishedThread = 0;   //記錄文件下完的數字
    //肯定下載地址
    static String path = "http://192.168.13.13:8080/QQPlayer.exe";
    public static void main(String[] args) {
        
        //發送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("QQPlayer.exe");
                //生成臨時文件
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                //設置臨時文件的大小
                raf.setLength(length);
                raf.close();
                //計算出每一個線程應該下載多少字節
                int size = length / ThreadCount;
                
                for (int i = 0; i < ThreadCount; i++) {
                    //計算線程下載的開始位置和結束位置
                    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請求,下載原文件
        try {
            File progressFile = new File(threadId + ".txt");
            //判斷進度臨時文件是否存在
            if(progressFile.exists()){
                FileInputStream fis = new FileInputStream(progressFile);
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                //從進度臨時文件中讀取出上一次下載的總進度,而後與本來的開始位置相加,獲得新的開始位置
                startIndex += Integer.parseInt(br.readLine());
                fis.close();
            }
            System.out.println("線程" + threadId + "的下載區間是:" + startIndex + "---" + endIndex);
            HttpURLConnection conn;
            URL url = new URL(MultiDownload.path);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            //設置本次http請求所請求的數據的區間
            conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
            
            //請求部分數據,相應碼是206
            if(conn.getResponseCode() == 206){
                //流裏此時只有1/3原文件的數據
                InputStream is = conn.getInputStream();
                byte[] b = new byte[1024];
                int len = 0;
                int total = 0;
                //拿到臨時文件的輸出流
                File file = new File("QQPlayer.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);
                    
                    //生成一個專門用來記錄下載進度的臨時文件
                    RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
                    //每次讀取流裏數據以後,同步把當前線程下載的總進度寫入進度臨時文件中
                    progressRaf.write((total + "").getBytes());
                    progressRaf.close();
                }
                System.out.println("線程" + threadId + "下載完畢-------------------小志參上!");
                raf.close();
                
                //把記錄進程的文件刪除    必須3個進程所有都下載完成後才能夠刪除
                MultiDownload.finishedThread++;
                synchronized (MultiDownload.path) {  //有線程安全問題,靜態變量爲惟一的
                    if(MultiDownload.finishedThread == MultiDownload.ThreadCount){
                        for (int i = 0; i < MultiDownload.ThreadCount; i++) {
                            File f = new File(i + ".txt");
                            f.delete();
                        }
                        MultiDownload.finishedThread = 0;
                    }
                }
                
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索