别再被坑!PHP7.1 下 ZipArchive 根本不能加密 zip,多文件加密正确姿势在这里
2025-09-29
一、问题背景
在业务开发中,我们经常需要对文件进行 压缩打包并加密,比如用户上传的文件需要打包成 zip 后再提供下载,或者在 API 里生成带密码的压缩包,提升安全性。
一开始,很多人(包括我)都会自然想到:
👉 PHP 自带的 ZipArchive
,调用 $zip->setPassword('xxx')
不就行了吗?
结果实际跑下来,压缩包生成了,但用 WinRAR / 7-Zip 打开时 完全不提示输入密码,文件还是明文的!
于是,我开始了一场 “为什么 PHP7.1 的 ZipArchive 不加密” 的踩坑之旅。
二、第一次尝试:ZipArchive + setPassword()
我最初写的代码大概长这样:
$zip = new \ZipArchive(); $zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); foreach ($files as $file) { $zip->addFile($file, basename($file)); } $zip->setPassword('123456'); $zip->close();
结果:
zip 文件能打开;
但完全没加密!
后来查文档才发现:
setPassword()
只是设置密码上下文,不会自动加密文件;真正加密要配合
setEncryptionName()
或setEncryptionIndex()
;而这两个方法是 PHP7.2+ 才有的!
👉 坑点 #1:PHP7.1 的 ZipArchive 根本不支持加密写入,只能解密已有压缩包。
三、第二次尝试:setEncryptionName()
我升级到新环境测试:
$zip->setPassword('123456'); $zip->setEncryptionName('test.txt', \ZipArchive::EM_AES_256);
这才发现 AES-256 加密是真正可用的。但坏消息是:在 PHP7.1 里完全没有这个方法。
👉 坑点 #2:AES 加密必须 PHP7.2+ + 新版 libzip,7.1 压根没有。
四、退而求其次:系统命令 zip -P
既然 PHP7.1 自带的 ZipArchive
不行,我只能换思路:
利用系统里的 zip
命令来完成加密。
改造后的代码:
$fileList = implode(' ', array_map('escapeshellarg', $files)); $cmd = "LANG=en_US.UTF-8 zip -j -P " . escapeshellarg($password) . " " . escapeshellarg($zipFile) . " " . $fileList; exec($cmd, $output, $resultCode); if ($resultCode === 0) { echo "压缩成功"; } else { echo "压缩失败"; }
效果:
多文件压缩 ✅
打开 zip 时提示输入密码 ✅
兼容 WinRAR/7-Zip ✅
这里我也踩到一个小坑:
👉 文件路径或密码里可能带空格/特殊符号,如果直接拼接字符串,命令会出错甚至被注入。
所以要用 escapeshellarg()
包裹参数,才能安全可靠。
五、最终结论
在 PHP7.1 里:
ZipArchive::setPassword()
只能用来 解密,不会加密;没有
setEncryptionName()
方法,无法开启 AES 加密;👉 别再幻想用 ZipArchive 来加密 zip 文件了!
解决方案:
能升级 PHP → 上到 7.2+,用
setEncryptionName()
,支持 AES-128/192/256;不能升级 PHP → 用系统命令
zip -P
,简单粗暴;更高需求 → 引入第三方库 nelexa/php-zip,支持 AES。
实践建议:
多文件加密 → 推荐直接用系统命令(配合
escapeshellarg
避免注入);生产环境安全性要求高 → 升级到支持 AES 的 PHP;
千万别再被
$zip->setPassword()
迷惑了,以为它能加密。
六、踩坑经验总结
看到文档≠能用,要注意不同 PHP 版本和 libzip 版本差异;
setPassword()
在 PHP7.1 根本不会加密,它只是“解密密码”;多文件加密最靠谱的方法就是调用系统命令
zip -P
;安全性更高的 AES 加密,需要 PHP7.2+ 或第三方库。
📢 一句话总结:
在 PHP7.1 下,
ZipArchive
根本无法实现真正的加密压缩,唯一稳妥的办法是调用系统zip -P
命令,或者升级到支持 AES 的 PHP7.2+。
发表评论: