ziparchive扩展需手动启用,非composer安装;php原生仅支持传统zip加密解压,不支持aes,密码解压须在open后调用setpassword()且仅限php 7.2+。

确认系统是否支持 ziparchive 扩展
PHP-Zip 并不是一个独立的 Composer 包,而是依赖 PHP 内置的 ziparchive 扩展。如果 ziparchive 未启用,装任何“PHP-Zip”包都没用——常见错误是直接 composer require php-zip 或类似名字,结果运行时报 Class 'ZipArchive' not found。
- 运行
php -m | grep zip检查扩展是否已加载(Linux/macOS) - Windows 用户检查
php.ini中是否取消注释了extension=zip -
phpinfo()页面里搜索 “zip” 确认 “Zip enabled” 为 true - 注意:部分 Docker 镜像(如
php:alpine)默认不带 zip 扩展,需额外安装apk add zip并启用扩展
使用 ZipArchive::setPassword() 解压带密码 ZIP
ZipArchive 自 PHP 7.2 起原生支持设置解压密码,但仅限于传统 ZIP 加密(即 PKZIP Legacy Encryption),不支持 AES 加密格式。很多用户误以为能解 WinRAR 或 7-Zip 生成的 AES 密码 ZIP,实际会静默失败或报错 ZipArchive::extractTo(): Invalid or uninitialized Zip object。
- 必须在
open()成功后、extractTo()前调用setPassword() - 密码只对当前打开的 ZIP 文件生效,不全局持久化
- 示例关键步骤:
$zip = new ZipArchive();
if ($zip->open('protected.zip') === TRUE) {
$zip->setPassword('123456'); // 必须在这之后再 extract
$zip->extractTo('./output/');
$zip->close();
} else {
echo "无法打开 ZIP 文件";
}
如何判断 ZIP 是否用了 AES 加密(而非传统加密)
没有通用 PHP 函数能直接读取 ZIP 加密方式,但可通过行为和错误间接识别:AES 加密 ZIP 在调用 setPassword() 后仍解压失败,且 ZipArchive::getStatusString() 返回空或无意义信息。此时说明 PHP 原生不支持,需换方案。
- 用命令行验证:
unzip -l -P dummy_password protected.zip—— 若提示 “skipping: xxx.txt password incorrect (password incorrect?)”,大概率是 AES - Linux/macOS 下可临时用
7z x protected.zip -p123456测试是否能解;若成功,则需调用外部命令 - 不要尝试用
exec('unzip -P ...')传密码,因为 unzip 的密码参数在某些版本中会被 shell 截断或泄露到进程列表 - 更安全做法:用
proc_open()启动7z并通过 stdin 输入密码(需确保服务器已安装p7zip-full)
Composer 不该装什么,以及替代方案建议
搜索 “php zip password” 容易找到一些 Composer 包(如 robrichards/zipstream、nelexa/zip),但它们都不支持解密,仅用于生成 ZIP。目前没有稳定、维护良好的 Composer 包能完整替代 ZipArchive 处理密码 ZIP。
- 别装
php-zip、ziparchive这类名字的包——它们要么是空壳,要么是旧版封装,不解决密码问题 - 如果必须支持 AES,务实做法是:检测到传统加密失败后,降级调用系统
7z或unzip(需提前验证命令可用性与权限) - 注意:Web 服务执行外部命令时,路径、超时、输入长度都可能出问题;例如密码含空格或特殊字符,必须用
escapeshellarg()包裹
真正卡住的地方往往不是代码怎么写,而是没意识到 ZIP 加密有两套互不兼容的标准,以及 PHP 只实现了其中一种。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











