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

Java 檔案上傳組件對決:SmartUpload vs Commons FileUpload 深度比較與選型指南

     編輯:Java 相關知識

前言

檔案上傳是 Web 開發高頻需求。早期 SmartUpload 佔據統治地位,後來 Apache Commons FileUpload 以串流處理、低記憶體佔用成為主流選擇。本文從原理、程式碼、效能三維度對比,並給出遷移建議。

一、SmartUpload (已停止維護)

核心特點

  • 將整個請求內容完整讀入記憶體解析,再寫入磁碟。
  • API 簡單,SmartUpload.upload() 一鍵完成。
  • 單一 SmartUpload.jar 無額外依賴。

典型程式碼

SmartUpload su = new SmartUpload();
su.initialize(pageContext);
su.setMaxFileSize(500 * 1024 * 1024); // 500MB
su.upload();

for (int i = 0; i < su.getFiles().getCount(); i++) {
    com.jspsmart.upload.File file = su.getFiles().getFile(i);
    if (!file.isMissing()) {
        file.saveAs(savePath + file.getFileName(), su.SAVE_PHYSICAL);
    }
}

致命缺陷

  • 大檔案/多檔案上傳時記憶體飆升:整個 multipart 請求載入 Heap,易導致 OutOfMemoryError。
  • 容器需重啟才能恢復:記憶體碎片化、臨時檔案未清理,導致後續上傳失敗,唯有重啟 Tomcat 解決。
  • 專案官網已不可訪問,社群停止維護超過十年。

二、Commons FileUpload (現役主流)

核心特點

  • 串流式處理:解析請求時將檔案內容直接寫入臨時檔案 (DiskFileItem),僅在記憶體保留小檔案 (閾值可配置)。
  • 介面導向設計:FileItem, FileItemFactory, FileUpload 易於擴充 (如資料庫儲存、雲端儲存)。
  • 支援 Servlet 3.0+ @MultipartConfig 原生整合。

典型程式碼

DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(4096);           // 4KB 以下存記憶體
factory.setRepository(new File("D:/Tomcat5/TEMP")); // 臨時目錄

ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(10_000_000);        // 10MB 單檔上限
upload.setSizeMax(50_000_000);            // 50MB 總請求上限

List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
    if (!item.isFormField()) {            // 過濾一般表單欄位
        String fileName = new File(item.getName()).getName(); // 防路徑遍歷
        item.write(new File("D:/UploadTest", fileName));
    }
}

三、關鍵指標對比表

指標SmartUploadCommons FileUpload
記憶體模型全量載入 Heap閾值分流:小檔案記憶體、大檔案磁碟
大檔案支援差 (易 OOM)優 (GB 級可上傳)
並發穩定性低 (需重啟容器)高 (無狀態、線程安全)
API 靈活度單一巨石類介面導向、可替換儲存策略
維護狀態停止維護 (2005 年後無更新)活躍維護 (最新 1.5 版 2023 年釋出)
依賴無commons-io

四、遷移建議與最佳實踐

  1. 直接替換:Controller/Action 層邏輯幾乎無需變動,僅更換解析上傳請求的工具類。
  2. 安全加固:
    • 檔案名稱清理:new File(item.getName()).getName() 防止目錄遍歷。
    • MIME 類型驗證:結合 Apache Tika 或 magic numbers 檢測真實檔案類型。
    • 病毒掃描整合:上傳完成後非同步呼叫 ClamAV/ICAP 掃描。
  3. 超大檔案斷點續傳:Commons FileUpload 單檔案不支援分片;需前端切片 (Plupload/Uppy) + 後端合併,或改用 Resumable.js + 自定義 FileItemFactory。
  4. Servlet 3.0+ 環境:可直接使用 request.getParts() 標準 API,零依賴,但缺乏進階流控 (大小限制、臨時目錄) 需在 @MultipartConfig 或 web.xml 配置。

五、作者後記:為什麼最終放棄 HTTP 上傳

「HTTP 方式傳檔案效率始終很低,我們現在使用 Web 方式實現的 FTP 檔案上傳。」

對於 GB 級、跨國、弱網環境大檔案傳輸,HTTP/1.1 缺乏並行、斷點續傳、壓傳輸層優化。現代方案:

  • 對象儲存直傳:前端簽名直傳 S3/OSS/GCS,後端僅驗證回調。
  • Tus.io 開放協定:HTTP 基礎上實現斷點續傳、分片上傳,支援多語言伺服端實作。
  • WebRTC DataChannel / WebSocket:內網 P2P 或低延遲雙向傳輸。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved