原系統使用 ajaxFileUpload 上傳 2GB 文件無問題,但客戶後續需求上傳 4GB 甚至 20GB 文件。在 IE11(32位)下,ajaxFileUpload 會拋出「算術結果超過 32 位」異常。經調研,選擇百度 WebUploader(HTML5 + Flash 双模式),支持分片並發上傳,兼容 IE6+、iOS 6+、Android 4+,且可自定義 UI 樣式。
<link rel="stylesheet" href="webuploader.css">
<script src="jquery.min.js"></script>
<script src="webuploader.min.js"></script>
Uploader.swf 由 WebUploader 內部加載,初始化時指定 swf 路徑即可。
var uploader = WebUploader.create({
auto: false, // 手動觸發上傳
pick: { id: '#attach', multiple: false },
swf: '../../main/js/Uploader.swf',
server: 'ContentsDetail!ajaxAttachUpload.action',
chunked: true, // 啟用分片
chunkSize: 5 * 1024 * 1024, // 5MB/片
threads: 1, // 串行上傳,保證順序
formData: { // 額外表單字段
status: 'file',
'contentsDto.contentsId': '0000004730',
uploadNum: '0000004730',
existFlg: 'false'
},
disableGlobalDnd: true // 禁用全局拖拽
});
fileQueued:文件加入隊列,渲染列表 UI。uploadAccept:服務端響應校驗,非成功碼則 return false 中斷並 reset。uploadSuccess/Error:更新狀態文案,失敗時 cancelFile + removeFile + reset。uploader.upload()。pick.multiple: true,name: 'multiFile'。startUpload 事件中彙總所有文件大小、名稱,通過 formData 一次性傳給後端。uploader.getFiles() 清理所有文件。public void ajaxAttachUpload() {
String path = "d:\\test\\" + fileFileName;
try {
File temp = this.getFile(); // Struts2 自動注入上傳臨時文件
FileUtil.randomAccessFile(path, temp); // 斷點續寫核心
if (StringUtils.isEmpty(chunk)) { // 單片/小文件
outJson("0", "success", "");
} else if (Integer.parseInt(chunk) == Integer.parseInt(chunks) - 1) { // 最後一片
outJson("0", "上傳成功", "");
} else {
outJson("2", "上傳中 chunk:" + chunk, "");
}
} catch (Exception e) {
outJson("3", "上傳失敗", "");
}
}
public static void randomAccessFile(String outPath, File src) throws IOException {
try (RandomAccessFile raf = new RandomAccessFile(new File(outPath), "rw");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(src))) {
raf.seek(raf.length()); // 定位到文件末尾(追加模式)
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
raf.write(buf, 0, len);
}
}
}
關鍵點:RandomAccessFile 的 seek(length()) 實現斷點續傳;多線程並發上傳同一文件時需加鎖(此處 threads:1 避開並發問題)。
UUID + 原文件名 存儲,避免覆蓋。checkChunk),後端維護已上傳分片記錄。item.delete() 刪除 WebUploader 產生的臨時分片文件。uploadProgress 事件,根據 file.loaded / file.size 更新 UI。WebUploader 憑藉分片並發、良好兼容性、靈活 API,成為 Java 後端大文件上傳的首選方案。前端配置分片參數,後端用 RandomAccessFile 追寫合併,即可穩健支撐 20GB+ 文件上傳。生產環境建議補全 MD5 秒傳、分片校驗、異常重試、存儲服務解耦(如對接 OSS)等能力。