方案一:自訂 ImageResult 繼承 ActionResult(最彈性)
public class ImageResult : ActionResult {
public ImageFormat ContentType { get; set; }
public Image Image { get; set; }
public string SourceName { get; set; }
public ImageResult(string sourceName, ImageFormat contentType) {
SourceName = sourceName; ContentType = contentType;
}
public ImageResult(Image image, ImageFormat contentType) {
Image = image; ContentType = contentType;
}
public override void ExecuteResult(ControllerContext context) {
var resp = context.HttpContext.Response;
resp.Clear();
resp.Cache.SetCacheability(HttpCacheability.NoCache);
string mime = ContentType.Equals(ImageFormat.Bmp) ? "image/bmp" :
ContentType.Equals(ImageFormat.Gif) ? "image/gif" :
ContentType.Equals(ImageFormat.Icon) ? "image/vnd.microsoft.icon" :
ContentType.Equals(ImageFormat.Jpeg) ? "image/jpeg" :
ContentType.Equals(ImageFormat.Png) ? "image/png" :
ContentType.Equals(ImageFormat.Tiff) ? "image/tiff" :
ContentType.Equals(ImageFormat.Wmf) ? "image/wmf" : "application/octet-stream";
resp.ContentType = mime;
if (Image != null) Image.Save(resp.OutputStream, ContentType);
else resp.TransmitFile(SourceName);
}
}
Controller 使用
public ActionResult GetPicture(int id) {
var server = new CategoryServer();
byte[] buffer = server.GetCategoryPicture(id);
if (buffer != null) {
using (var ms = new MemoryStream(buffer)) {
var img = Image.FromStream(ms);
return new ImageResult(img, ImageFormat.Jpeg);
}
}
return View(); // 或回傳預設圖片
}
方案二:FileResult 直接輸出實體檔案
public FileResult Image() {
string path = Server.MapPath("/Content/Images/Decorative/");
string fileName = Request.Url.Segments.Last();
string fullPath = Path.Combine(path, fileName);
return File(fullPath, "image/jpeg");
}
方案三:File 方法簡化版
public ActionResult Image(string id) {
var dir = Server.MapPath("/Images");
var path = Path.Combine(dir, id + ".jpg");
return File(path, "image/jpg");
}
方案四:FileStreamResult 支援大檔案串流(可改造為資料庫讀取)
[AcceptVerbs(HttpVerbs.Get)]
[OutputCache(CacheProfile = "CustomerImages")]
public FileResult Show(int customerId, string imageName) {
var path = Path.Combine(ConfigData.ImagesDirectory, customerId.ToString(), imageName);
return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
}
方案比較
| 方案 | 適用場景 | 優點 | 缺點 |
| ImageResult | 資料庫二進位、動態處理(水印、縮圖) | 完全控制、支援多種格式 | 程式碼較多 |
| FileResult (實體路徑) | 靜態檔案、CDN 同步 | 簡潔、自動處理 Range/ETag | 需實體檔案 |
| File() | 簡單靜態圖片 | 一行搞定 | 彈性低 |
| FileStreamResult | 大檔案、資料庫 Blob 串流 | 記憶體友善、支援斷點續傳 | 需手動管理 Stream 生命週期 |
最佳實務建議
- 靜態圖片:直接用 `
` 走 IIS 靜態檔案處理,效能最好。
- 資料庫圖片:採用 ImageResult 或 FileStreamResult,並加上
OutputCache 快取。
- 安全性:避免直接暴露資料庫 ID,改用 GUID 或加密 Token;驗證用戶權限後再輸出。
- MIME 類型:嚴格對應副檔名,防止內容嗅探攻擊。