筆記目錄

Skip to content

ASP.NET Core Web API 檔案上傳處理方式的實踐探討

TLDR

  • 推薦採用「檔案上傳與業務邏輯分離」的架構,將檔案上傳獨立為單一 API,業務資料僅傳遞檔案 ID。
  • 使用 [FromForm] 處理檔案上傳,使用 [FromBody] 處理 JSON 業務資料,可避免兩者混用導致的 ModelBinder 實作複雜化。
  • 檔案上傳獨立後,建議透過排程任務清理未啟用的暫存檔案,避免伺服器空間浪費。
  • 檔案下載建議整合於業務邏輯 Controller 中,以利實作細粒度的權限控管。
  • 針對檔案驗證,建議在 Service 層處理,避免在 Request Input 的 ValidationAttribute 中直接依賴資料庫。

檔案上傳處理模式分析

在 ASP.NET Core Web API 中,常見的檔案處理方式主要分為表單提交與 Base64 字串傳輸。

使用表單 Submit 或 FormData

什麼情況下會遇到:當開發者希望維持傳統表單提交方式,或檔案體積較大不適合轉為字串時。

  • 優點:不增加資料傳輸量。
  • 缺點:
    • 系統同時存在 [FromBody][FromForm] 會導致 ModelBinderJsonConverter 處理邏輯不一致,增加維護成本。
    • 對前端影響大,若 API 原本僅支援 JSON,新增檔案功能時需大幅調整前端傳輸格式。

使用 JSON 傳遞 Base64 字串

什麼情況下會遇到:當前後端希望統一使用 JSON 格式進行資料交換,且檔案體積較小時。

  • 優點:前後端處理邏輯一致,API 格式統一。
  • 缺點:資料大小會增加約 1.33 倍,可能造成效能瓶頸。

推薦方案:檔案上傳與業務資料提交分離設計

為了兼顧效能與 API 一致性,建議將檔案上傳與業務邏輯拆分。

實作流程

  1. 檔案上傳 API:使用 [FromForm] 接收檔案,存儲至檔案伺服器並寫入檔案資料表,回傳檔案 ID。
  2. 業務資料 API:新增或修改資料時,僅傳遞檔案 ID,而非檔案內容。
  3. 資料管理機制
    • 業務資料新增時,將檔案狀態標記為「啟用」。
    • 設定排程任務,定期清理一天以上未啟用的檔案及其資料表記錄。
    • 刪除業務資料時,可選擇同步刪除關聯檔案或標記為「非啟用」。

檔案驗證實作

若需在驗證時存取資料庫,可透過 validationContext 取得 Service。

csharp
protected override ValidationResult IsValid(
    object value, ValidationContext validationContext
) {
    using IServiceScope scope = validationContext.CreateScope();
    IFileService service = scope.ServiceProvider.GetRequiredService<IFileService>();
    // 執行驗證邏輯
}

WARNING

檔案類型驗證具有局限性,除了 .exe 檔案外,大多數檔案類型難以透過簽名完全識別,且容易產生誤判。建議將涉及資料庫的複雜驗證邏輯移至 Action 或 Service 層處理。

檔案下載實作考量

將檔案上傳獨立後,下載功能可選擇通用 API 或業務邏輯整合。

  • 通用檔案下載 API:實作簡單,但難以針對不同業務場景實作細粒度的權限控制。
  • 業務邏輯 Controller 下載:建議採用此方式,雖然各模組需撰寫下載邏輯,但可確保權限控管的嚴謹性。

TIP

為減少重複程式碼,可建立基礎的檔案下載服務類(Service),封裝通用下載邏輯,再由各業務模組透過依賴注入(DI)呼叫。

異動歷程

  • 2025-03-10 初版文件建立。