核心 HTTP 標頭設定(所有方式通用)
Response.ContentType = "application/octet-stream"; // 或具體 MIME
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8));
Response.AddHeader("Content-Length", fileSize.ToString()); // 若可預知
方式一:Response.TransmitFile(推薦大檔案)
Response.TransmitFile(filePath); // 直接由 IIS 核心模式傳送,不經 ASP.NET 記憶體
Response.End();
- 優點:不佔用 Managed Heap 記憶體、支援 >2GB 檔案、IIS 核心快取、自動處理斷點續傳(Range 標頭)。
- 適用:生產環境大檔案下載首選。
方式二:Response.WriteFile(簡單易用)
Response.Clear();
Response.WriteFile(filePath);
Response.Flush();
Response.End();
- 內部同樣使用
TransmitFile,但會先載入檔案資訊,中型檔案適用。
方式三:Response.WriteFile 分塊讀取(控制記憶體)
const int ChunkSize = 102400; // 100KB
byte[] buffer = new byte[ChunkSize];
using (FileStream fs = File.OpenRead(filePath))
{
long remaining = fs.Length;
while (remaining > 0 && Response.IsClientConnected)
{
int read = fs.Read(buffer, 0, ChunkSize);
Response.OutputStream.Write(buffer, 0, read);
Response.Flush();
remaining -= read;
}
}
Response.Close();
- 優點:固定緩衝區,記憶體佔用恆定,適合超大檔或高併發。
- 關鍵:檢查
Response.IsClientConnected 避免用戶取消後繼續佔用資源。
方式四:FileStream + BinaryWrite(傳統完整讀取)
byte[] bytes = File.ReadAllBytes(filePath); // 一次性載入記憶體!
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
- 缺點:大檔案易導致
OutOfMemoryException、LOT(大物件堆)碎片化、**不推薦生產環境使用**。
方式五:FileStream 手動分塊寫入 OutputStream(精細控制)
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buffer = new byte[81920]; // 80KB
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0 && Response.IsClientConnected)
{
Response.OutputStream.Write(buffer, 0, bytesRead);
Response.Flush();
}
}
- 與方式三類似,但使用
FileShare.Read 允許其他程序同時讀取。
方式六:MVC FileResult / ASP.NET Core PhysicalFileResult(現代化)
// ASP.NET MVC
return File(filePath, "application/octet-stream", fileName);
// ASP.NET Core
return PhysicalFile(filePath, "application/octet-stream", fileName); // 自動支援 Range、ETag、快取
- 框架層級封裝,自動處理 Range 請求、快取標頭、非同步傳輸,**新專案首選**。
比較總結表
| 方式 | 記憶體 | 大檔案 | 斷點續傳 | 複雜度 | 推薦指數 |
| TransmitFile | 極低 | ✅ 最佳 | ✅ IIS 原生 | 低 | ⭐⭐⭐⭐⭐ |
| WriteFile | 低 | ✅ | ❌ | 低 | ⭐⭐⭐⭐ |
| 分塊 WriteFile | 固定低 | ✅ | ❌ 需自行處理 Range | 中 | ⭐⭐⭐⭐ |
| BinaryWrite 全讀 | 高 (OOM 風險) | ❌ | ❌ | 低 | ⭐ |
| 手動 FileStream | 固定低 | ✅ | ❌ 需自行處理 | 中 | ⭐⭐⭐ |
| FileResult / PhysicalFile | 極低 | ✅ 最佳 | ✅ 框架自動 | 極低 | ⭐⭐⭐⭐⭐ |
實務建議
- **舊版 Web Forms**:優先
TransmitFile,極大檔或需自訂邏輯用分塊。
- **MVC 5**:使用
File() 回傳 FilePathResult。
- **ASP.NET Core**:直接
PhysicalFile() 或 FileStreamResult,支援非同步 FileStreamResultAsync。
- **安全性**:檔案路徑嚴格驗證,防止路徑遍歷攻擊;
Content-Disposition 檔名務必 UrlEncode。
- **效能**:啟用 IIS 靜態內容快取、輸出快取;CDN 分發大型公開檔案。