首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 多線程斷點續傳下載器:命令列版完整實作

     編輯:Java 程式設計入門

功能特色

  • 支援 HTTP Range 請求 實現斷點續傳。
  • 多線程並發下載 同一檔案(示例啟動兩個執行緒下載同一 URL)。
  • 本地檔案大小與遠端 Content-Length 比對,自動判斷是否續傳或已完成。
  • 獨立進度顯示執行緒,每 5 秒輸出下載百分比。
  • 使用 RandomAccessFile 定位寫入位置。

核心類別結構

Download 主類別

public class Download {
    public static void main(String[] args) {
        String url = "https://example.com/largefile.zip";
        new Thread(new Downloader(url)).start();
        new Thread(new Downloader(url)).start(); // 模擬多線程
    }
}

Downloader 實作 Runnable

class Downloader implements Runnable {
    private static final String SAVE_DIR = "E:\\download";
    private final String url;
    private final String fileName;

    static { new File(SAVE_DIR).mkdirs(); }

    public Downloader(String url) {
        this.url = url;
        this.fileName = url.substring(url.lastIndexOf('/') + 1);
    }

    @Override public void run() {
        try { download(); System.out.println(fileName + " 下載完成"); }
        catch (Exception e) { e.printStackTrace(); }
    }

    private void download() throws Exception {
        RandomAccessFile raf = new RandomAccessFile(SAVE_DIR + File.separator + fileName, "rw");
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(url);

        long localSize = getLocalSize();
        long remoteSize = getRemoteSize(client, get);

        // 續傳條件
        if (localSize != -1 && remoteSize != -1 && localSize < remoteSize) {
            raf.seek(localSize);
            get.addHeader("Range", "bytes=" + localSize + "-" + (remoteSize - 1));
        } else if (localSize >= remoteSize) {
            raf.close(); return; // 已完成
        }

        HttpResponse resp = client.execute(get);
        if (resp.getStatusLine().getStatusCode() / 100 == 2) {
            // 進度顯示執行緒
            new Thread(() -> {
                try {
                    while (raf.length() < remoteSize) {
                        System.out.printf("%s 已下載: %.2f%%%n", fileName,
                            raf.length() * 100.0 / remoteSize);
                        Thread.sleep(5000);
                    }
                } catch (Exception ignored) {}
            }).start();

            // 寫入資料
            try (InputStream in = resp.getEntity().getContent()) {
                byte[] buf = new byte[512];
                int len;
                while ((len = in.read(buf)) != -1) raf.write(buf, 0, len);
            }
        }
        raf.close();
        client.getConnectionManager().shutdown();
    }

    private long getLocalSize() {
        File f = new File(SAVE_DIR, fileName);
        return f.exists() ? f.length() : -1;
    }

    private long getRemoteSize(HttpClient client, HttpGet get) throws Exception {
        HttpResponse resp = client.execute(get);
        int code = resp.getStatusLine().getStatusCode();
        if (code / 100 == 2) return resp.getEntity().getContentLength();
        return -1;
    }
}

關鍵技術點解析

技術說明
Range 標頭Range: bytes=START-END 告知伺服器只傳輸指定區間,206 Partial Content 回應。
RandomAccessFileseek(pos) 移動檔案指標,配合 rw 模式實現隨機讀寫。
多線程進度獨立執行緒輪詢 raf.length() 計算百分比,避免阻塞下載主流程。
HttpClient 4.x範例使用 DefaultHttpClient(已棄用),建議升級至 HttpClient 5 或 OkHttp。

生產環境強化建議

  1. 分段下載:將檔案切分多段,每段由獨立線程下載,最後合併,大幅提速。
  2. 校驗完整性:下載完成後驗證 MD5/SHA-256。
  3. 錯誤重試:網路波動時指數退避重試。
  4. 限速/暫停/恢復:提供控制介面。
  5. 圖形介面:Swing/JavaFX 顯示進度條、速度、剩餘時間。

依賴 (Maven)

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.13</version>
</dependency>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved