在企業級 ASP.NET 應用開發中,大檔案上傳始終是技術難點之一。當檔案大小超過 100MB 時,傳統的上傳方式往往面臨請求逾時、記憶體溢出、無法顯示進度等問題。本文深入剖析兩款主流上傳組件——AspnetUpload 2.0 與 Lion.Web.UpLoadModule 的核心實現原理,揭示基於 HttpWorkerRequest 的底層數據流讀取機制,並展示如何透過 HttpModule 實現大檔案分塊上傳與即時進度監控。
這兩款組件均採用 Chris Hynes 提出的 HttpModule 方案,核心在於利用 IIS 為 ASP.NET 建立的命名管道,透過 HttpWorkerRequest 的 GetPreloadedEntityBody 與 ReadEntityBody 方法,從管道中分塊讀取上傳數據。這種方式繞過了 ASP.NET 預設的整體請求緩衝機制,避免大檔案一次性載入記憶體導致的效能瓶頸。
在 HttpModule 的 Init 事件中攔截請求,首先驗證 Content-Type 是否為 multipart/form-data,並檢查 HasEntityBody 確認存在實體內容。獲取 Content-Length 標頭以得知總檔案大小,為後續進度計算奠基。
調用 GetPreloadedEntityBody 取得 IIS 預載的初始數據塊(通常為 48KB),解析出 UploadGUID(唯一上傳標識)、UploadFolder(儲存路徑)等關鍵元數據。此階段同時初始化 Progress 物件記錄接收位元組數、檔案名稱、檔案總數,並存入 Application 狀態供前端輪詢進度。
當 IsEntireEntityBodyIsPreloaded 為 false 時,進入循環調用 ReadEntityBody 逐塊讀取剩餘數據(預設緩衝區 200KB)。每讀取一塊即更新 Progress.ReceivedLength,並透過 RequestStream 處理 multipart 邊界分隔,將檔案內容寫入磁碟。若偵測到 !Response.IsClientConnected 則中斷上傳並清理資源。
上傳完成後,將所有讀取的位元組陣列合併,調用 PopulateRequestData 重填充至 HttpWorkerRequest,使後續 ASP.NET Pipeline 能正常存取 Request.Files、Request.Form 等集合,實現與標準上傳流程的無縫銜接。
HttpWorkerRequest request1 = (HttpWorkerRequest)((IServiceProvider)HttpContext.Current).GetService(typeof(HttpWorkerRequest));
byte[] buffer2 = request1.GetPreloadedEntityBody();
num1 += buffer2.Length;
// 解析 UploadGUID、UploadFolder 等元數據
// 初始化 Progress 物件並存入 Application["_UploadGUID_" + guid]
while ((num2 - num1) >= bufferSize) {
if (!application1.Context.Response.IsClientConnected) { ClearApplication(application1); }
num3 = request1.ReadEntityBody(buffer3, buffer3.Length);
num1 += num3;
// 透過 RequestStream 處理邊界、寫入檔案、更新進度
progress1.ReceivedLength = num1;
application1.Application["_UploadGUID_" + text2] = progress1;
}
web.config 註冊 HttpModule;對負載平衡、Web Farm 環境需共享 Application 狀態(建議改用 Redis/資料庫)。ASP.NET Core 時代,建議採用 IFormFile 流式讀取、MultipartReader 或第三方庫(如 MultipartFormDataParser)配合 SignalR 實現進度推送;或採用分片上傳(Chunked Upload)配合前端切片庫(Uppy、Dropzone),由後端合併分片,更適應雲原生與容器化部署。
HttpModule + HttpWorkerRequest 方案在 .NET Framework 時期為大檔案上傳提供了經典解法,其分塊讀取、進度追蹤、請求重構的設計思想至今仍具參考價值。理解底層管道機制,有助於在遷移至現代架構時做出更合理的技術選型。