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

Java 實現 HTTP 斷點續傳核心原理與完整工程代碼實戰

     編輯:Java 程式設計入門

斷點續傳 HTTP 協議原理

標準下載請求


GET /down.zip HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: */*
Connection: Keep-Alive

服務器響應 (200 OK)


HTTP/1.1 200 OK
Content-Length: 106786028
Accept-Ranges: bytes
Content-Type: application/octet-stream
Last-Modified: Mon, 30 Apr 2001 12:56:11 GMT
ETag: "02ca57e173c11:95b"

斷點續傳請求 (Range 請求)


GET /down.zip HTTP/1.1
Host: www.example.com
User-Agent: NetFox
Range: bytes=2000070-    # 從第 2000070 字節開始

服務器響應 (206 Partial Content)


HTTP/1.1 206 Partial Content
Content-Length: 104785958
Content-Range: bytes 2000070-106786027/106786028
Content-Type: application/octet-stream

關鍵點:狀態碼 206、Content-Range 標識返回片段範圍、Accept-Ranges: bytes 聲明支持範圍請求。

Java 核心 API 實現


// 1. 建立連接
URL url = new URL("https://www.example.com/down.zip");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// 2. 設置 Range 標頭
conn.setRequestProperty("Range", "bytes=" + startPos + "-");
conn.setRequestProperty("User-Agent", "NetFox");

// 3. 獲取輸入流 (自動處理 206 響應)
InputStream in = conn.getInputStream();

// 4. 隨機寫入文件 (RandomAccessFile)
RandomAccessFile raf = new RandomAccessFile("down.zip", "rw");
raf.seek(startPos);  // 定位文件指針

byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) > 0) {
    raf.write(buffer, 0, len);
}

完整多線程斷點續傳引擎實現

核心類設計

類職責
SiteFileFetch主控制器:文件信息獲取、分片策略、線程編排、進度持久化
FileSplitterFetch工作線程:單分片下載、斷點續傳邏輯、寫入協調
FileAccessI文件寫入封裝:RandomAccessFile 線程安全寫入
SiteInfoBean配置數據:URL、保存路徑、分片數
Utility工具類:睡眠、日誌

關鍵代碼片段

分片策略 (SiteFileFetch)


long fileLength = getFileSize(); // HEAD 請求獲取 Content-Length
int parts = bean.getNSplitter(); // 默認 5 片
long partSize = fileLength / parts;

for (int i = 0; i < parts; i++) {
    long start = i * partSize;
    long end = (i == parts - 1) ? fileLength : (i + 1) * partSize;
    nStartPos[i] = start;
    nEndPos[i] = end;
}

斷點續傳核心邏輯 (FileSplitterFetch.run)


while (nStartPos < nEndPos && !bStop) {
    HttpURLConnection conn = (HttpURLConnection) new URL(sURL).openConnection();
    conn.setRequestProperty("Range", "bytes=" + nStartPos + "-");
    
    try (InputStream in = conn.getInputStream()) {
        byte[] buf = new byte[1024];
        int read;
        while ((read = in.read(buf)) > 0 && nStartPos < nEndPos && !bStop) {
            nStartPos += fileAccess.write(buf, 0, read); // 寫入並更新位置
        }
    }
    bDownOver = true;
}

進度持久化 (定期保存/恢復)


// 保存:主線程定期調用
DataOutputStream out = new DataOutputStream(new FileOutputStream(tmpFile));
out.writeInt(nStartPos.length);
for (int i = 0; i < nStartPos.length; i++) {
    out.writeLong(fileSplitterFetch[i].nStartPos);
    out.writeLong(fileSplitterFetch[i].nEndPos);
}

// 恢復:構造器中讀取
DataInputStream in = new DataInputStream(new FileInputStream(tmpFile));
int count = in.readInt();
nStartPos = new long[count];
nEndPos = new long[count];
for (int i = 0; i < count; i++) {
    nStartPos[i] = in.readLong();
    nEndPos[i] = in.readLong();
}

文件寫入線程安全封裝


public class FileAccessI implements Serializable {
    private final RandomAccessFile raf;
    
    public FileAccessI(String fileName, long pos) throws IOException {
        raf = new RandomAccessFile(fileName, "rw");
        raf.seek(pos);
    }
    
    public synchronized int write(byte[] b, int off, int len) {
        raf.write(b, off, len);
        return len;
    }
}

工程化增強建議

  1. 校驗完整性:下載完成後驗證 MD5/SHA256,或分片級 CRC32
  2. 限速控制:Token Bucket 算法實現下載速度限制
  3. 連接復用:HTTP/1.1 Keep-Alive + 連接池,減少握手開銷
  4. 錯誤重試:指數退避重試機制,區分可重試/不可重試錯誤
  5. UI 進度回調:Observer 模式通知進度、速度、剩餘時間
  6. 現代替代方案:OkHttp 支持範圍請求、自動重試、連接池,生產環境建議直接使用

測試驗證


public class TestMethod {
    public static void main(String[] args) {
        SiteInfoBean bean = new SiteInfoBean(
            "https://localhost/largefile.exe", 
            "D:/downloads", 
            "largefile.exe", 
            5  // 5 線程
        );
        new SiteFileFetch(bean).start();
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved