PHP中ZipArchive打开空文件时为何删除文件?如何避免?
为什么ZipArchive打开空文件后会删除原文件?怎么避免?
你的代码如下:
file_put_contents('a.upl', ''); try { $x = new \ZipArchive(); $x->open('a.upl'); } catch(\Exception $e) { echo $e->getMessage(); }
原因分析
ZipArchive的open()方法默认使用ZipArchive::OVERWRITE模式(对应模式值0)。当你用这个模式打开一个不是有效Zip格式的文件(比如你创建的空文件)时,底层逻辑会尝试将该文件重写为合法的Zip归档。但空文件无法被识别为有效Zip,这个重写操作会失败,而过程中原文件已经被删除,最终就出现了文件消失的情况。
另外要注意:你写的try-catch其实没作用,因为这个操作只会抛出警告而非Exception,所以不会被捕获。
解决方法
1. 指定安全的打开模式
根据你的需求选择合适的模式,避免默认的覆盖模式:
- 如果只是要读取文件,用
ZipArchive::RDONLY只读模式,打开空文件会直接失败,不会修改原文件:
file_put_contents('a.upl', ''); $x = new \ZipArchive(); // 使用只读模式 $result = $x->open('a.upl', ZipArchive::RDONLY); if ($result !== true) { echo "打开失败,错误码:$result"; // 错误码会对应ZipArchive::ER_NOZIP(不是有效Zip) }
- 如果要创建/写入Zip,用
ZipArchive::CREATE模式,该模式只会在文件不存在时创建新文件,若文件存在且不是有效Zip则直接失败,不会删除原文件:
file_put_contents('a.upl', ''); $x = new \ZipArchive(); $result = $x->open('a.upl', ZipArchive::CREATE); if ($result !== true) { echo "打开失败,错误码:$result"; }
2. 打开前先做有效性检查
在调用open()前,先判断文件是否为空或者是否是有效Zip:
$file = 'a.upl'; file_put_contents($file, ''); // 检查文件大小是否为0 if (filesize($file) === 0) { echo "文件为空,无法作为Zip归档打开"; } else { $x = new \ZipArchive(); $result = $x->open($file); if ($result !== true) { echo "打开失败:" . $x->getStatusString(); } }
3. 捕获警告信息(可选)
如果需要捕获警告,可以通过设置错误处理函数将警告转为异常:
set_error_handler(function($errno, $errstr) { throw new \RuntimeException($errstr); }, E_WARNING); file_put_contents('a.upl', ''); try { $x = new \ZipArchive(); $x->open('a.upl'); } catch(\RuntimeException $e) { echo $e->getMessage(); } finally { restore_error_handler(); }
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

