finfo_file() 是 PHP 8.4 获取 MIME 类型的唯一可靠方式,因 mime_content_type() 已被彻底移除;它基于文件魔数识别,比 $_FILES['type'] 和后缀名更安全,且需配合 is_readable() 和 finfo_close() 正确使用。
finfo_file() 是 PHP 8.4 获取 MIME 类型的唯一可靠方式PHP 8.4 已彻底移除 mime_content_type() 函数(自 PHP 8.0 起已弃用),调用它会直接触发 Deprecated: mime_content_type(): Function mime_content_type() is deprecated 错误,甚至在严格模式下直接报 Fatal error。这不是警告,是硬性淘汰。必须改用基于 finfo 扩展的方案,且该扩展在 PHP 8.4 中默认启用、无需额外安装。
finfo_open() + finfo_file() 安全获取文件 MIME 类型核心流程是:创建资源 → 检测文件 → 关闭资源。漏掉 finfo_close() 不会立即出错,但长期运行可能耗尽系统资源。
FILEINFO_MIME_TYPE:只返回类型(如 image/jpeg),最常用FILEINFO_MIME:返回完整 MIME 字符串(如 image/jpeg; charset=binary),含分号和参数,多数场景不需要is_readable() 判断,避免 finfo_file() 返回 false 后无提示function getMimeType(string $filePath): ?string
{
if (!is_readable($filePath)) {
return null;
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
if ($finfo === false) {
return null;
}
$type = finfo_file($finfo, $filePath);
finfo_close($finfo);
return $type ?: null;
}
// 使用示例
$mimeType = getMimeType('/var/www/uploads/photo.jpg');
// 返回 'image/jpeg' 或 null
finfo 和 $_FILES['xxx']['type'] 的本质区别
浏览器提交的 $_FILES['xxx']['type'] 是客户端自行设置的字符串,完全不可信——用户可伪造为任意值(如 application/x-php 上传 .php 文件)。而 finfo 是服务端基于文件内容魔数(magic bytes)识别,真实反映文件二进制结构。绕过 finfo 直接信任 $_FILES 的 type 字段,在 PHP 8.4 下等于主动引入文件上传漏洞。
.jpg,内容可能是 PHP 代码,finfo 会返回 text/x-php
finfo 可能返回 image/png 或 application/octet-stream,取决于 libmagic 数据库版本finfo_file() 返回 false 却没检查这是线上最隐蔽的问题之一——函数失败时返回 false,而非抛出异常。若直接赋值给变量并用于后续逻辑(比如 switch 判断),会导致空值或类型错误,且难以定位。
$type = finfo_file($finfo, $path); if ($type === 'image/*') { ... }
fals
e 或空字符串finfo_buffer($finfo, file_get_contents($path)) 测试内存中数据,排除文件权限/路径问题finfo_open() 失败,大概率是系统缺少 magic 数据库文件,需检查 php --ri fileinfo 输出中的 libmagic version 和 magic file 路径别指望靠后缀名或 $_FILES 字段保安全,PHP 8.4 把路封死了,finfo 不是可选项,是必选项。漏掉 is_readable() 检查或忽略 finfo_file() 的 false 返回值,上线后第一个上传请求就可能崩。