PHP ZipArchive 有很多坑,一不小心就会让你掉进坑里,让看似正常的程序得不到预期的结果。
- ZipArchive 创建或者打开的 zip 文档,在 ZipArchive::close() 这个方法被调用之前,只是在操作一个临时的文件,只有在调用了 close() 方法之后,压缩文档才会真正的开始完成文件的操作和保存工作,如果没有在代码里面明确调用 close() 这个方法,PHP 会在代码最后自动去调用。
比如很多人遇到的问题,先将一个文件压缩进 zip 文档中,然后将文件删除,如以下代码,当 addFile() 调用完成以后,虽然函数返回了 true,但是这个时候 PHP 并没有真的地将文件加入到压缩文件中,而只是对添加文件到压缩包这件事情做了一个“登记”,直到 $za->close() 被调用的时候才会真正地去添加文件到压缩包中,然而很遗憾的是,如下代码中,在执行实际添加文件的操作的时候,文件已经被删除了,因此程序会出错,无论之前对压缩文件做过多少操作,都回到了最初的状态,因为压缩文件没有创建成功,如果该压缩文件早前已经存在,文件不会有任何变化。参见:PHP压缩文件夹和子目录为zip文件 使用内置ZipArchive类实现- <?php
- $za = new ZipArchive();
- $za->open('./xc.zip', ZipArchive::CREATE|ZipArchive::OVERWRITE);
- $file = './notes.txt';
- if( true === $za->addFile($file)){
- unlink($file);
- }
- if(!$za->close()){
- echo 'failure.';
- }
- ?>
复制代码
- ZipArchive::addFile($file, $saveAs) 如果 $file 是一个目录的路径,会导致程序出错,无论你之前做过多少操作,直接回到解放前,文件不会创建成功,如果该压缩文件早前已经存在,文件不会有任何变化,更气人的是,如果目录真实存在的的话,它的返回值还是 true.
因此,如果通过 scandir() 之类的函数获取目录的文件列表的话,一定要记得把返回的文件列表中的子目录给删除掉,只保留子目录里面的文件。
参见:ZipArchive addFile 传递的参数是文件夹时将导致整个代码失效 - 如果 ZipArchive open() 了一个不存在的文件,并且你使用了 ZipArchive::OVERWRITE ,你经过一翻折腾,最终没有文件写入到压缩文件中,那么你会遇到 “ZipArchive::close(): Can't remove file: No such file or directory” 这个错误,要破解这个问题,要么不要用 ZipArchive::OVERWRITE,自己用代码去检查要创建的文件是否已经存在,如果存在就删除它;要么每次 open() 一个不存在的文件后,先向压缩文件中先写入一个无关紧要的文件。
|
|