ZipArchive无法直接删除ZIP内文件,必须重建ZIP:遍历条目跳过logs/前缀路径,用getFromName读取内容写入新ZIP,并注意空目录处理、路径匹配精度及大文件流式操作。
用
删除 ZIP 包里的
目录及其中文件
PHP 原生不支持直接“删除 ZIP 内文件”,
没有
方法。必须重建 ZIP:打开原包 → 遍历所有条目 → 跳过匹配
前缀的路径 → 把其余内容写入新 ZIP。
关键点是路径判断要严格,避免误删(比如
不该被删):
用
或正则
判断前缀
返回 -1 表示不存在,但遍历时不需要它
务必用
读取原始二进制内容,别用
新建 ZIP 时建议加
标志,避免残留旧文件
清空 logs 后保留原 ZIP 结构(含空目录)?做不到
ZIP 规范里没有“空目录”实体 —— 只有带结尾
的路径条目(如
)才表示目录。如果你删了
但想保留
目录条目,得手动补上:
遍历完所有文件后,检查是否曾遇到过
条目(即
)
如果没有,且你确实需要这个空目录,调用
但注意:
在 PHP 7.4+ 才稳定;低版本只能写个空字符串进
路径模拟
大多数场景下,删光
下所有文件 + 目录条目本身,就是真正的“清空”
用
调用系统
命令更简单?慎用
Linux/
mac
OS 下可用
,看起来一行解决。但实际踩坑多:
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
不递归删除子目录(
无效),得先
PHP 可能禁用
(
里含它)
路径含空格或特殊字符时,
容易断开,需加
和
配合
Windows 上
命令默认不存在,得额外部署 Info-ZIP 或 7-Zip
权限问题:Web 进程可能没权限修改 ZIP 文件(尤其在
外)
性能与大文件注意事项
处理几百 MB 的 ZIP 时,内存和时间容易爆:
别一次性
全部内容再写入新 ZIP —— 改用流式:对每个非
条目,
读,
直接写入新 ZIP 的
但注意:
封装协议不支持写入,所以流式仍得靠
+ 分块
超大 ZIP(>500MB)建议改用临时磁盘解压 → 删除
→ 重新压缩,反而更稳
记得
,否则反复操作同一文件时
可能返回旧值
真正麻烦的是路径匹配逻辑和边缘情况 —— 比如
、
(不是目录)、
是否该删。这些得按你业务规则硬
编码
判断,没法靠一个通用函数兜底。
ziparchivelogs/ZipArchivedelete()logs/application/logs_backup/substr($name, 0, 5) === 'logs/'^logs/$zip->locateName($name)$zip->getFromName($name)file_get_contents()ZIPARCHIVE::OVERWRITE/logs/logs/error.loglogs/logs/$name === 'logs/'$newZip->addEmptyDir('logs')addEmptyDir()logs/logs/shell_execzipzip -d archive.zip "logs/*"zip -d"logs/**"zipinfo -1 archive.zip | grep '^logs/' | xargs -I{} zip -d archive.zip "{}"shell_execdisable_functionsxargs-0zipinfo -Tzip/tmp$zip->getFromName()logs/fopen('zip://'.$oldPath.'#'.$name, 'r')fwrite()fopen('zip://'.$newPath.'#'.$name, 'w')zip://ZipArchive::addFromString()fread()logs/clearstatcache()filesize()LOGS/logs.phpapp/logs/