真实 mime 类型必须基于文件魔数或底层 api 分析二进制头,path.getextension 仅返回扩展名,与 mime 无关;推荐使用 microsoft.aspnetcore.webutilities.fileheaders 或手动读取前若干字节校验魔数。

用 Path.GetExtension 只能拿到后缀,不是 MIME 类型
很多人以为文件扩展名能代表类型,比如 .jpg 就是 image/jpeg,但这是靠不住的——改个后缀名就能骗过它。系统根本不看内容,只查字符串匹配。真实 MIME 类型必须基于文件“魔数”(magic bytes)或调用底层 API 分析二进制头。
-
Path.GetExtension返回的是".pdf"这种字符串,和 MIME 无关 - 仅靠扩展名映射(如
new Dictionary<string string> { [".png"] = "image/png" }</string>)在用户上传、文件重命名、无后缀等场景下必然出错 - Windows 上注册表有扩展名到 MIME 的映射,但 .NET 不默认读它;Linux/macOS 更没统一来源
推荐用 Microsoft.AspNetCore.WebUtilities.FileHeaders(ASP.NET Core 内置)
如果你项目已引用 Microsoft.AspNetCore.WebUtilities(常见于 ASP.NET Core Web API 或 MVC),它提供轻量、无依赖的头检测逻辑,比自己写魔数匹配更稳。
- 支持常见格式:PNG、JPEG、GIF、PDF、ZIP、XML、JSON、TXT、MP4 等约 30+ 种
- 只读前 256 字节,不加载整个文件,内存友好
- 不依赖系统组件或外部库,跨平台可用
- 示例:
using Microsoft.AspNetCore.WebUtilities; // ... var mimeType = FileHeaders.GetContentType(filePath); // 返回 "image/jpeg" 或 null
纯 .NET 6+ 可用 System.IO.Path.GetExtension + 手动魔数校验(无 ASP.NET 依赖)
若项目是控制台、WinForms 或没引入 ASP.NET 包,就得自己判断头字节。别硬背所有魔数,只覆盖你实际要处理的类型即可。
- JPEG 开头通常是
FF D8 FF(3 字节),PNG 是89 50 4E 47(4 字节),PDF 是25 50 44 46 - 用
FileStream打开并Read前 4 字节足够区分大部分类型,避免File.ReadAllBytes加载大文件 - 注意字节序和编码:魔数是十六进制原始字节,不是 UTF-8 字符串
- 示例片段:
byte[] header = new byte[4]; using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4, FileOptions.SequentialScan); _ = fs.Read(header, 0, header.Length); if (header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47) return "image/png";
别碰 UrlMon.dll 的 FindMimeFromData(Windows 专属且已废弃)
老教程常提这个 COM 接口,但它在 Windows 10/11 上行为不稳定,对新格式(如 AVIF、WebP)识别率低,而且需要 P/Invoke + 权限 + 注册表配合,容易抛 AccessViolationException 或返回 "application/octet-stream"。
- 微软文档明确标注为 “legacy”,.NET 6+ 官方不推荐
- 在容器、Linux、CI 环境中根本不可用
- 即使调通,返回值也不符合 IANA MIME 标准(比如返回
image/x-png而非image/png)










