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

Struts 文件上傳實戰 (六):Action 文件寫入磁盤與業務入庫邏輯

     編輯:Java 程式設計入門

代碼定位

原文標題為「struts構建文件上傳(六)」,內容即上文補充的 MaintainAction。本文深度剖析其文件寫入、DAO 調用與轉發邏輯,並指出生產級隱患。

核心流程圖解

MaintainAction.execute()
    │
    ├─► 1. 獲取 FormFile (theFile1)
    │
    ├─► 2. 讀取輸入流 → 寫入服務器磁盤 (FileOutputStream)
    │       └─ 關鍵:buffer 8KB、循環寫入、關閉流、destroy() 臨時文件
    │
    ├─► 3. 設置 trainPlan.p_accessory = 文件名
    │
    ├─► 4. trainPlanDAO.addTrainPlan(trainPlan) 入庫
    │
    └─► 5. request.setAttribute("trainPlain", trainPlan) → forward("trainplanCreated")

生產級隱患清單與修正方案

隱患風險修正方案
request.getRealPath("/") 獲取路徑WAR 解壓路徑不穩定,重新部署文件丟失;Windows/Linux 路徑分隔符差異配置外部化上傳目錄(servletContext.initParameter、NFS、S3/OSS)
文件名直接用原名 theFile.getFileName()重名覆蓋、特殊字符注入、路徑遍歷攻擊 (../../etc/passwd)生成 UUID 文件名 + 原始名存資料庫;FilenameUtils.getName() 防遍歷
無文件類型/大小驗證惡意上傳腳本、大文件撐爆磁盤白名單驗證 Content-Type/擴展名;struts.multipart.maxSize + 代碼雙重限制
單線程同步寫入大文件阻塞 Web 線程,併發下吞吐量劇降異步處理(線程池/消息隊列)、前端直傳對象存儲
DAO 直接 new,無事務管理文件寫入成功但入庫失敗 → 數據不一致;連接洩漏Spring @Transactional 統一事務;連接池管理 DataSource
異常捕獲後僅 printStackTrace用戶無感知,日誌難追蹤統一異常處理器,記錄結構化日誌,返回友好錯誤頁

重構版核心代碼片段

// 服務層方法(Spring @Service + @Transactional)
public Trainplan createTrainPlan(Trainplan plan, List files) {
    List savedNames = new ArrayList<>();
    for (FormFile file : files) {
        if (file == null || file.getFileSize() == 0) continue;
        validateFile(file); // 類型、大小
        String storedName = storeFile(file); // 寫入配置目錄或 OSS,返回 UUID 名
        savedNames.add(storedName);
    }
    plan.setAttachments(String.join(",", savedNames)); // 或關聯表批量插入
    trainPlanDAO.insert(plan);
    return plan;
}

// Action 僅做轉換與跳轉
public ActionForward execute(...) {
    try {
        Trainplan plan = maintainForm.getTrainPlan();
        List files = Arrays.asList(
            maintainForm.getTheFile1(), maintainForm.getTheFile2(), maintainForm.getTheFile3()
        );
        Trainplan saved = trainPlanService.createTrainPlan(plan, files);
        request.setAttribute("trainPlan", saved); // 修正拼寫 trainPlan
        return mapping.findForward("success");
    } catch (BusinessException e) {
        saveErrors(request, e.getActionMessages());
        return mapping.getInputForward();
    }
}

遷移建議

  • Struts 1.x → Spring MVC:FormFile → MultipartFile,Action → @Controller,ActionForm → @ModelAttribute / DTO。
  • 文件存儲:本地磁盤 → MinIO/S3/OSS,資料庫存 bucket/key,應用無狀態化支援水平擴展。
  • 前端直傳:簽名直傳 OSS,回調業務 API 保存元數據,徹底卸載 Web 服務器 I/O 壓力。

經典代碼承載了時代記憶,重構思路才是永恆價值。

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