ziparchive 在 php 7.3 中支持批量压缩解压,但需手动遍历文件、校验路径、转换中文名编码、控制内存,不能一键操作;open() 不自动覆盖文件,addfile() 路径需 utf-8 编码且避免绝对路径,extractto() 需防路径穿越并手动建目录。

ZipArchive 在 PHP 7.3 中已稳定支持,但部分行为和参数兼容性需特别注意。直接说结论:能批量压缩解压,但必须手动遍历文件、校验路径、处理中文名和内存限制,不能靠 extractTo() 或 addFile() 一键搞定整个目录。
ZipArchive::CREATE 在 PHP 7.3 下的 open() 行为差异
PHP 7.3 的 ZipArchive::CREATE 不会自动覆盖同名 ZIP 文件——如果目标文件已存在且不可写,open() 返回 ZIPARCHIVE::ER_EXISTS(不是 0),而非静默覆盖。
常见错误现象:Warning: ZipArchive::open(): No such file or directory 实际是权限或路径问题,但返回码被忽略导致后续 addFile() 失败。
- 务必检查
$zip->open($file, ZipArchive::CREATE)的返回值,用=== TRUE判断(不能用== true) - 若需覆盖,改用
ZipArchive::CREATE | ZipArchive::OVERWRITE - 路径必须是绝对路径,相对路径在 CLI 和 Web 环境下行为不一致,容易漏掉文件
批量添加文件时 addFile() 的路径陷阱
addFile() 第二个参数(归档内路径)决定 ZIP 中的结构。PHP 7.3 默认按字节写入,不自动转换编码,中文文件名会乱码或被截断。
- 如果源文件路径含中文,
addFile($realPath, $archiveName)中的$archiveName必须是 UTF-8 编码(Web 通常已是),但 Windows 下 PHP 7.3 可能默认 GBK,需显式mb_convert_encoding($name, 'UTF-8', 'GBK') - 避免传入绝对路径作为
$archiveName,否则 ZIP 里会出现C:\xxx\file.txt这种非法路径;应统一用basename($realPath)或基于源目录计算相对路径 -
addFile()对不存在的文件静默失败,不报错也不抛异常,必须用file_exists($realPath)预检
大目录递归压缩的内存与性能控制
PHP 7.3 默认 memory_limit=128M,压缩百个以上小文件或单个 >50MB 文件极易 OOM。不能依赖 RecursiveDirectoryIterator 一次性加载全部路径。
- 用
glob($dir . '/*.php', GLOB_NOSORT)分批获取,比scandir()+ 手动过滤更安全 - 对每个文件调用
addFile()前,检查filesize($path) (10MB),超限改用 <code>addFromString(basename($path), file_get_contents($path))并unset($content)释放内存 - 不要在循环里反复
$zip->close()再$zip->open()—— PHP 7.3 的ZipArchive实例不支持多次 open/close 同一文件,会导致资源泄漏或损坏 ZIP
extractTo() 解压时的路径穿越与空目录问题
extractTo() 在 PHP 7.3 中不会自动创建中间目录,也不会拒绝 ../ 路径,直接调用等于开放任意文件写入。
- 必须对每个
getNameIndex($i)返回的文件名做白名单校验:!preg_match('/^\.\./', $name) && strpos($name, '../') === false - 遇到以
/结尾的条目(即目录),需手动mkdir($dest . '/' . $name, 0755, true),extractTo()本身不建空目录 - 解压后建议用
clearstatcache()清除文件状态缓存,否则后续is_dir()可能误判
PHP 7.3 的 ZipArchive 功能完整,但容错弱、编码敏感、路径处理全靠手动——最容易被忽略的是 open() 返回值判断和中文名编码转换,这两个点出错,ZIP 要么打不开,要么解压出来一堆乱码文件。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











