在 PHP 中,finfo 是一个非常实用的扩展,用于获取文件的 MIME 类型、编码等元信息。相比传统的 mime_content_type() 函数,finfo 提供了更为准确且灵活的功能。正确地使用 finfo 可以有效防止文件类型伪装,提高文件处理的安全性。本文将详细介绍使用 finfo 的几种正确方式以及常见注意事项。
最常见的用途是获取文件的 MIME 类型,例如判断一个上传文件是否为图片或 PDF。
<?php
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file('/path/to/file.pdf');
echo $mimeType;
上述代码中,FILEINFO_MIME_TYPE 告诉 finfo 返回的是 MIME 类型,如 application/pdf 或 image/jpeg。这是判断文件类型的标准方式。
有时文件内容不一定保存在磁盘上,而是通过变量传入,如 API 上传。可以使用 finfo_buffer 方法:
<?php
$finfo = new finfo(FILEINFO_MIME_TYPE);
$data = file_get_contents('https://gitbox.net/sample.png');
$mimeType = $finfo->buffer($data);
echo $mimeType;
这种方式适合处理流式数据或远程抓取的内容。
finfo 在文件上传中的典型应用是验证文件内容与扩展名是否匹配,从而防止用户上传恶意脚本文件伪装成图片。
<?php
if ($_FILES['upload']['error'] === UPLOAD_ERR_OK) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($_FILES['upload']['tmp_name']);
$allowedTypes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'application/pdf' => 'pdf',
];
if (!array_key_exists($mimeType, $allowedTypes)) {
die('不支持的文件类型。');
}
$ext = $allowedTypes[$mimeType];
move_uploaded_file($_FILES['upload']['tmp_name'], "/uploads/file.$ext");
}
通过对比 finfo 检测的 MIME 类型和预设的白名单,可以有效防止非法文件上传。
文件扩展名容易被篡改,仅依赖扩展名判断文件类型是不安全的。应始终使用 finfo 检查实际内容。
某些老版本的 PHP 环境可能未启用 fileinfo 扩展。可以通过 phpinfo() 或 extension_loaded('fileinfo') 检查。
<?php
if (!extension_loaded('fileinfo')) {
die('fileinfo 扩展未启用');
}
finfo->file() 需要文件存在且具有读取权限,否则可能返回 application/octet-stream 或 false。
除了 FILEINFO_MIME_TYPE,还可以使用 FILEINFO_MIME 获取更详细的信息,如编码格式:
<?php
$finfo = new finfo(FILEINFO_MIME);
$info = $finfo->file('/path/to/file.txt');
echo $info; // 例如 text/plain; charset=us-ascii
这种方式在处理多语言文档或编码转换时特别有用。
使用 finfo 是 PHP 中识别文件类型最安全和可靠的方式之一。无论是上传文件验证、远程数据分析,还是系统自动化任务,掌握并正确使用 finfo 都能为应用带来更高的稳定性与安全性。只需确保开启 fileinfo 扩展,并结合 MIME 白名单判断,就能构建一个更加稳健的文件处理流程。