用戶上傳文件可能修改擴展名(如 .exe 改為 .jpg),單靠擴展名/MIME 判斷極不靠須。需讀取文件二進制頭部特徵碼(Magic Number)確認真實格式。
public static class ImageUtility {
// 方法一:文件路徑 → Base64 字符串
public static string Base64String(string virtualPath) {
string physicalPath = Server.MapPath(virtualPath);
byte[] bytes = File.ReadAllBytes(physicalPath);
return Convert.ToBase64String(bytes);
}
// 方法二:Base64 字符串 → 判斷是否圖片
public static bool IsImage(string base64String) {
byte[] bytes = Convert.FromBase64String(base64String);
using (MemoryStream ms = new MemoryStream(bytes)) {
return IsImage(ms); // 核心判斷邏輯
}
}
// 核心:讀取文件頭特徵碼
private static bool IsImage(Stream stream) {
byte[] header = new byte[8];
stream.Read(header, 0, 8);
// JPEG: FF D8 FF
// PNG: 89 50 4E 47 0D 0A 1A 0A
// GIF: 47 49 46 38 37/39 61
// BMP: 42 4D
return CheckSignature(header);
}
// 重載:直接接收 HttpPostedFileBase(上傳時驗證)
public static bool IsImage(HttpPostedFileBase file) {
using (Stream stream = file.InputStream) {
return IsImage(stream);
}
}
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file) {
if (file != null && ImageUtility.IsImage(file)) {
// 保存邏輯
return Json(new { success = true });
}
return Json(new { success = false, msg = "非圖片文件" });
}
| 格式 | 文件頭(十六進制) |
|---|---|
| JPEG | FF D8 FF |
| PNG | 89 50 4E 47 0D 0A 1A 0A |
| GIF | 47 49 46 38 37 61 / 47 49 46 38 39 61 |
| BMP | 42 4D |
| WebP | 52 49 46 46 ... 57 45 42 50 |
最佳實踐:上傳時同步做擴展名白名單 + MIME 類型檢查 + 文件頭驗證三重過濾;存儲時重命名為 GUID + 正確擴展名,避免路徑遍歷攻擊。