利用瀏覽器內建下載功能,透過 FileResult 系列返回檔案流,自動觸發「另存新檔」對話框。本文涵蓋實體檔案、記憶體流、大檔案分塊、中文檔名編碼、Content-Disposition 標頭完整處理。
public ActionResult Download() {
var path = Server.MapPath("~/Files/report.pdf");
return File(path, "application/pdf", "報表.pdf"); // 瀏覽器彈出下載,檔名「報表.pdf」
}

| 類型 | 適用場景 | 建構參數 |
|---|---|---|
FilePathResult | 磁碟實體檔案 | File(path, contentType, fileName) |
FileContentResult | 記憶體位元組陣列 | File(byte[], contentType, fileName) |
FileStreamResult | 任意 Stream (大檔、網路流、壓縮流) | File(stream, contentType, fileName) |
PhysicalFileResult | Core 專用,支援 Range 請求 (斷點續傳) | PhysicalFile(path, contentType, fileName) |
VirtualFileResult | Core 專用,虛擬路徑 (IFileProvider) | File(virtualPath, contentType, fileName) |
public ActionResult DownloadWithChineseName() {
var path = Server.MapPath("~/Files/報表.pdf");
var fileName = "報表.pdf";
var encodedFileName = Uri.EscapeDataString(fileName); // UTF-8 百分號編碼
var cd = new ContentDisposition {
FileName = fileName, // 兼容舊瀏覽器 (IE)
FileNameStar = $"UTF-8''{encodedFileName}" // RFC 5987: 現代瀏覽器
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(path, "application/pdf");
}
public ActionResult DownloadLargeFile() {
var path = Server.MapPath("~/Files/big.iso");
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan);
// SequentialScan 提示 OS 循序讀取,減少緩衝區污染
return File(stream, "application/octet-stream", "big.iso");
}
// 注意:Stream 由 MVC 管線自動 Dispose,無需手動 using
[HttpGet]
public IActionResult DownloadRange(string file) {
var path = _env.ContentRootFileProvider.GetFileInfo(file).PhysicalPath;
return PhysicalFile(path, "application/octet-stream", file, enableRangeProcessing: true);
// 自動處理 Request.Headers["Range"],返回 206 Partial Content
}
public ActionResult ExportExcel() {
using (var ms = new MemoryStream()) {
using (var pkg = new ExcelPackage(ms)) {
var ws = pkg.Workbook.Worksheets.Add("Data");
ws.Cells[1,1].Value = "Hello";
pkg.Save();
}
ms.Position = 0;
return File(ms.ToArray(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Export.xlsx");
}
}
Path.GetFullPath(path).StartsWith(allowedRoot),拒絕 ../../etc/passwd。application/x-msdownload、text/html 等可執行/腳本類型。FileStreamResult / PhysicalFileResult,避免 byte[] 導致 LOH 壓力。FileNameStar (UTF-8)。FileName (需 URL 編碼),FileNameStar 會被忽略。FileNameStar,但舊版可能需 filename*=UTF-8''... 格式。Content-Type 非文字類型、Content-Disposition: attachment。