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

ChunkUpload 斷點續傳組件:Java 服務端與 JS 客戶端集成全攻略

     編輯:Java 綜合教學

ChunkUpload 斷點續傳組件:Java 服務端與 JS 客戶端集成全攻略

ChunkUpload 是一款零依賴、高性能、支持多用戶協作上傳的 Java 斷點續傳組件。採用文件切片 + MD5 秒傳 + 斷點續傳架構,客戶端利用 Web Worker、FileReader、XHR2 等現代 API 實現大文件高效上傳。本文詳細講解服務端集成、客戶端調用、存儲結構、配置調優與示例代碼。

一、核心特性速覽

  • ✅ 斷點續傳:網絡中斷/瀏覽器關閉後,刷新頁面可恢復上傳。
  • ✅ 秒傳/多用戶協作:同一文件 (MD5+大小相同) 多用戶並行上傳,自動合併進度,越多人越快。
  • ✅ 線程安全 + 進程安全:同一物理機多實例部署共享存儲目錄無衝突。
  • ✅ 自動切片/合併:4MB/片,上傳完成可選立即合併或異步合併。
  • ✅ 低內存佔用:流式處理,不將整文件載入內存。
  • ✅ 零第三方依賴:Servlet 3.0+ / JRE 7+ 即可運行。

二、服務端集成 (3 步完成)

1. 引入 Jar

<dependency>
    <groupId>com.iyangyuan</groupId>
    <artifactId>chunkupload</artifactId>
    <version>1.0</version>
</dependency>

2. 配置 web.xml

<servlet>
    <servlet-name>ChunkUpload</servlet-name>
    <servlet-class>com.iyangyuan.chunkupload.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ChunkUpload</servlet-name>
    <url-pattern>/chunkupload/*</url-pattern>
</servlet-mapping>

建議:放在 Shiro 等安全過濾器之後,Spring MVC 之前,確保權限校驗生效且不被 MVC 攔截。

3. 創建 chunkupload.properties (classpath 根目錄)

# 文件存儲根目錄 (多實例部署請指向共享存儲,如 NFS/S3 掛載點)
root=/data/chunkupload

# 文件鎖緩存容量 (根據併發調整,默認 2048)
fileLockCapacity=2048

# 上傳完成是否立即合併切片 (強烈建議 false,異步合併避免長時間阻塞響應)
createFile=false

三、客戶端集成 (現代瀏覽器專用)

支持矩陣

瀏覽器支持備註
Chrome 10+ / Firefox 4+✅ 完美Web Worker + File API 全支持
Edge 12+ / Safari 10+✅ 完美
360/國產雙核 (WebKit 模式)✅ 支持需啟用極速模式
IE 所有版本❌ 不支持缺乏 Web Worker/Blob.slice 支持

引入腳本

<script src="/static/lib/dawn/dawn.js"></script> <!-- MD5 計算,性能優化 50% -->
<script src="/static/lib/chunkupload/chunkupload.js"></script> <!-- 核心上傳邏輯 -->

四、核心 JS API 詳解

1. ChunkUpload 類 — 文件上傳主入口


// 實例化
var cu = new ChunkUpload(file); // file 為 input.files[0]

// 啟動上傳 (四個異步回調)
cu.upload({
    success: function(block) {
        // 上傳成功,block 為文件控制對象
        console.log("上傳完成", block.info());
    },
    error: function(msg) {
        console.error("上傳失敗:", msg);
    },
    md5Progress: function(percent) {
        console.log("MD5 計算進度:", percent + "%");
    },
    uploadProgress: function(percent) {
        console.log("上傳進度:", percent + "%");
    }
});

// 中斷上傳 (任意時刻)
cu.abort();

2. Block 類 — 文件級控制 (秒傳/查詢/刪除)


// 實例化 (需知道文件 MD5 和大小,可從成功回調的 block 獲取,或服務端返回)
var block = new Block("f1154ca6fab7f3628927c1268f3570fd", 20879935);

// 獲取文件信息 (切片列表、狀態、大小)
block.info(function(info) {
    console.log(JSON.stringify(info));
    /* 輸出示例:
    {
      "status": 0,
      "data": {
        "chunks": [{"md5":"e114c2...", "n":1}, ...],
        "chunkNum": 5,
        "md5": "f1154ca...",
        "state": 1,  // 1=完成, 0=未完成
        "size": 20879935
      }
    }
    */
}, function(status, errMsg) {
    console.error("查詢失敗:", errMsg);
});

// 刪除服務端文件 (所有切片 + 元數據)
block.delete(function(result) {
    console.log("刪除結果:", result);
}, function(status, errMsg) {
    console.error("刪除失敗:", errMsg);
});

五、服務端存儲結構解密


/data/chunkupload/                          # root 配置目錄
└── 07/12/87/                               # MD5 前6位,每兩位一級目錄
    └── 071287fffa974b878732a7a17858be3620879935/  # 目錄名 = MD5 + 文件大小
        ├── chunk_1.bin                     # 切片 1 (4MB)
        ├── chunk_2.bin
        ├── chunk_3.bin
        ├── chunk_4.bin
        ├── chunk_5.bin                     # 最後一片可能 < 4MB
        ├── meta.dat                        # 元數據: 總大小、切片數、狀態、上傳用戶記錄
        └── lock.file                       # 文件級鎖 (防止併發合併衝突)

優勢:目錄分散避免單目錄文件過多導致文件系統性能下降;MD5+大小雙重校驗確保文件唯一性。

六、完整上傳頁面示例 (可直接複製運行)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ChunkUpload Demo</title>
    <style>
        body {font-family: sans-serif; max-width: 600px; margin: 2rem auto;}
        .progress-bar {width: 100%; height: 20px; background: #eee; border-radius: 10px; overflow: hidden; margin: 10px 0;}
        .progress-fill {height: 100%; background: #4caf50; width: 0%; transition: width 0.3s;}
        button {padding: 8px 16px; margin-right: 10px; cursor: pointer;}
        button:disabled {opacity: 0.5; cursor: not-allowed;}
    </style>
</head>
<body>
    <h3>大文件斷點續傳演示</h3>
    <input type="file" id="fileInput" />
    <br/><br/>
    <button id="startBtn" onclick="startUpload()">開始上傳</button>
    <button id="pauseBtn" onclick="pauseUpload()" disabled>暫停/取消</button>
    <div class="progress-bar"><div id="progressFill" class="progress-fill"></div></div>
    <p id="statusText">等待選擇文件...</p>

    <script src="/static/lib/dawn/dawn.js"></script>
    <script src="/static/lib/chunkupload/chunkupload.js"></script>
    <script>
        var cu, fileInput = document.getElementById('fileInput'),
            startBtn = document.getElementById('startBtn'),
            pauseBtn = document.getElementById('pauseBtn'),
            progressFill = document.getElementById('progressFill'),
            statusText = document.getElementById('statusText');

        function startUpload() {
            var file = fileInput.files[0];
            if (!file) return alert("請先選擇文件");
            
            startBtn.disabled = true; pauseBtn.disabled = false;
            cu = new ChunkUpload(file);
            
            cu.upload({
                md5Progress: function(p) { updateUI(p, "計算 MD5"); },
                uploadProgress: function(p) { updateUI(p, "上傳中"); },
                success: function(block) {
                    updateUI(100, "上傳完成 ✅");
                    startBtn.disabled = false; pauseBtn.disabled = true;
                    console.log("文件信息:", block.info());
                },
                error: function(msg) {
                    statusText.textContent = "失敗: " + msg;
                    startBtn.disabled = false; pauseBtn.disabled = true;
                }
            });
        }
        
        function pauseUpload() {
            if (cu) { cu.abort(); statusText.textContent = "已暫停/取消"; }
            startBtn.disabled = false; pauseBtn.disabled = true;
        }
        
        function updateUI(percent, label) {
            progressFill.style.width = percent + "%";
            statusText.textContent = label + " " + percent + "%";
        }
    </script>
</body>
</html>

七、生產環境調優建議

  1. 異步合併:createFile=false,啟動定時任務掃描 state=1 且未合併的目錄執行合併,避免上傳請求長時間持有連接。
  2. 共享存儲:集群部署時 root 指向 NFS/CephFS/MinIO 掛載點,確保多實例訪問同一物理文件。
  3. 安全策略:Servlet 後增加權限過濾器,校驗用戶身份、文件類型白名單、大小限制、防掃描令牌。
  4. 監控告警:埋點上傳耗時、失敗率、磁盤佔用、合併隊列積壓。
  5. 清理策略:定期掃描 state=0 且超過 7 天未活躍的臨時目錄,釋放磁盤空間。

ChunkUpload 以現代瀏覽器能力為基線,捨棄 IE 兼容性換取極致上傳體驗。對於內部管理系統、現代 Web 應用、大文件上傳場景,它是比 Plupload/WebUploader 更輕量、更原生、更易擴展的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved