应使用finfo扩展读取文件魔数判断真实类型,而非依赖扩展名或$_files['type'];启用fileinfo扩展后用finfo_open(fileinfo_mime_type)获取mime类型,如application/pdf;无法使用时可结合扩展名与前几kb魔数校验,pdf为%pdf-,docx等为pk\x03\x04。

PHP判断文档文件类型,不能只依赖文件扩展名,因为容易被伪造。核心方法是读取文件头部的“魔数”(Magic Number),结合 MIME 类型检测,才能更准确识别真实类型。
使用 finfo 扩展(推荐)
PHP 的 finfo 扩展基于 libmagic 库,能根据文件内容分析类型,是目前最可靠的方式。
- 确保 PHP 已启用
fileinfo扩展(php.ini 中取消;extension=fileinfo注释) - 用
finfo_open(FILEINFO_MIME_TYPE)获取 MIME 类型,如application/pdf、text/plain - 用
finfo_open(FILEINFO_MIME)可同时返回 MIME 类型和编码(如text/plain; charset=us-ascii)
示例代码:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, '/path/to/document.docx');
finfo_close($finfo);
if ($mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
echo '这是 .docx 文件';
}
检查文件扩展名 + 内容头(轻量备用)
当无法使用 finfo 时,可组合校验:先取扩展名做初步过滤,再读取前几百字节匹配常见魔数。
- PDF 文件开头通常是
%PDF- - DOCX/XLSX/PPTX 是 ZIP 格式,开头为
PK\x03\x04(十六进制) - 纯文本类(TXT、LOG、CSV)无固定魔数,但可用
mb_detect_encoding()辅助判断是否含二进制数据
注意:仅读取前 1–4 KB 即可,避免大文件性能问题。
处理上传文件时的类型验证
用户上传的 $_FILES['file']['type'] 字段由浏览器提供,完全不可信,必须忽略。
- 始终以服务端检测(如
finfo)为准 - 建议将临时文件先移到安全目录,再检测;确认类型后再重命名或入库
- 对敏感类型(如 DOCX、XLSX)可额外解压检查内部
[Content_Types].xml结构,防伪装 ZIP
常见文档 MIME 类型参考
便于比对判断结果:
-
text/plain— TXT、LOG、CSV(无 BOM) -
application/pdf— PDF -
application/msword— DOC -
application/vnd.openxmlformats-officedocument.wordprocessingml.document— DOCX -
application/vnd.oasis.opendocument.text— ODT -
application/rtf— RTF
不复杂但容易忽略:类型判断只是第一步,后续还需结合业务做权限控制、内容扫描或格式转换。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











