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]會導致ModelBinder與JsonConverter處理邏輯不一致,增加維護成本。 - 對前端影響大,若 API 原本僅支援 JSON,新增檔案功能時需大幅調整前端傳輸格式。
- 系統同時存在
使用 JSON 傳遞 Base64 字串
什麼情況下會遇到:當前後端希望統一使用 JSON 格式進行資料交換,且檔案體積較小時。
- 優點:前後端處理邏輯一致,API 格式統一。
- 缺點:資料大小會增加約 1.33 倍,可能造成效能瓶頸。
推薦方案:檔案上傳與業務資料提交分離設計
為了兼顧效能與 API 一致性,建議將檔案上傳與業務邏輯拆分。
實作流程
- 檔案上傳 API:使用
[FromForm]接收檔案,存儲至檔案伺服器並寫入檔案資料表,回傳檔案 ID。 - 業務資料 API:新增或修改資料時,僅傳遞檔案 ID,而非檔案內容。
- 資料管理機制:
- 業務資料新增時,將檔案狀態標記為「啟用」。
- 設定排程任務,定期清理一天以上未啟用的檔案及其資料表記錄。
- 刪除業務資料時,可選擇同步刪除關聯檔案或標記為「非啟用」。
檔案驗證實作
若需在驗證時存取資料庫,可透過 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 初版文件建立。
