php验证压缩文件需结合mime类型、文件头和解压探测三重手段:先过滤扩展名,再读取magic bytes校验,最后用ziparchive/phardata等扩展尝试打开确认可解析,任一环节失败即拒绝。

不能只靠文件扩展名判断压缩文件类型,PHP 验证压缩文件需结合 MIME 类型、文件头(magic bytes)和实际解压探测三重手段,否则容易被恶意伪造的文件绕过。
检查文件扩展名(基础但不可靠)
扩展名是最容易伪造的一环,仅作初步过滤,不作为验证依据:
- 允许常见的压缩后缀:.zip、.rar、.7z、.tar、.gz、.bz2、.xz
- 用
pathinfo($filename, PATHINFO_EXTENSION)提取后缀并转小写比对 - 注意:.tar.gz、.tar.bz2 等复合后缀需额外处理,建议统一按最终扩展名或双后缀逻辑判断
读取文件头字节(关键防线)
真实压缩格式在文件开头有固定签名(magic bytes),读取前 4–12 字节即可识别:
-
ZIP:以
50 4B 03 04(十六进制)开头(即字符串"PK\x03\x04") -
RAR:旧版为
52 61 72 21 1A 07 00("Rar!\x1a\x07\x00"),新版RAR5为52 61 72 21 1A 07 01 00 -
7z:以
37 7A BC AF 27 1C("7z\xbc\xaf'\x1c")开头 -
TAR:原始 tar 无固定签名,但 GNU tar 常以
00 00 00 00 00 00 00 00开头(全零块),更稳妥方式是尝试解析 tar header(512 字节结构) - 代码示例:
$header = file_get_contents($filepath, false, null, 0, 8);后用bin2hex($header)或直接字符串匹配
用 PHP 扩展执行轻量级解压探测
仅校验头信息仍可能漏判(如加密 ZIP 头部完整但内容异常),推荐调用系统命令或 PHP 扩展做最小化解析:
- 启用
ziparchive扩展时,用new ZipArchive()→open()返回值判断是否为有效 ZIP(返回ZIPARCHIVE::ER_NOZIP等即失败) - 对 TAR/GZ/BZ2,可用
phar扩展:$phar = new PharData($filepath); $phar->isCompressed();(需开启phar.readonly=0且支持对应格式) - 安全起见,禁用执行高危操作(如
extractTo()),仅做count()或getFileName()等只读探测 - 若环境允许,用
exec('file -b --mime-type ' . escapeshellarg($filepath), $out)调用系统file命令辅助判断(注意路径转义)
综合验证流程建议
将三步串联成白名单式校验链:
- 先过滤扩展名(快速拦截明显非法后缀)
- 再读取文件头,匹配已知压缩 magic bytes
- 最后用对应扩展(ZipArchive/PharData)尝试打开,确认可解析
- 任一环节失败即拒绝上传,不依赖单一结果
- 上传临时文件后立即验证,验证通过再移入正式目录,避免中间状态风险
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











