【PHP学习笔记】使用ZipArchive 创建zip包,总是不成功问题探究

提出问题:

 1 <?php
2 $zip = new ZipArchive;
3 var_dump($zip);
4 if ($zip -> open('test.zip',ZIPARCHIVE::CREATE) === TRUE) {
5 $zip->addFile('test.txt');
6 var_dump($zip);
7 $zip -> close();
8 echo 'ok';
9 } else {
10 echo 'failed';
11 }
12 ?>

问题就出在第5行!!!

第5行,test.txt这个文件必须已存在当前目录下(很重要),下面会看到,如果当前目录下没有这个文件,得到的结果很杯具,不报错,但是就是没有test.zip文件,下面看下输出信息(在第3行和第5行输出):

调试查看输出:

下图,是正确的情况,能够创建test.zip文件

object(ZipArchive)[1]
public 'status' => int 0
public 'statusSys' => int 0
public 'numFiles' => int 0
public 'filename' => string '' (length=0)
public 'comment' => string '' (length=0)
object(ZipArchive)[1]
public 'status' => int 0
public 'statusSys' => int 0
public 'numFiles' => int 1
public 'filename' => string 'G:\www\myweb\php\test\test.zip' (length=30)
public 'comment' => string '' (length=0)
ok

下图,是无法创建test.zip文件的情况

object(ZipArchive)[1]
public 'status' => int 0
public 'statusSys' => int 0
public 'numFiles' => int 0
public 'filename' => string '' (length=0)
public 'comment' => string '' (length=0)
object(ZipArchive)[1]
public 'status' => int 0
public 'statusSys' => int 0
public 'numFiles' => int 1
public 'filename' => string 'G:\www\myweb\php\test\test.zip' (length=30)
public 'comment' => string '' (length=0)
ok

对比2个输出,可见2个结果完全一样,而且也没报错,但是第二个情况,没有创建zip文件成功!!

使用XDebug:

同样2个情况 现在我从xdebug看下 执行过程以及各个变量变化:

首先看看正常创建zip文件的情况:

TRACE START [2011-11-28 02:59:41]
0.0022 104000 +104000 -> {main}() G:\www\myweb\php\test\zip.php:0
=> $zip = class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 0; public $filename = ''; public $comment = '' } G:\www\myweb\php\test\zip.php:2
0.0026 105136 +1136 -> var_dump(class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 0; public $filename = ''; public $comment = '' }) G:\www\myweb\php\test\zip.php:3
>=> NULL
0.0029 105208 +72 -> ZipArchive->open('test.zip', 1) G:\www\myweb\php\test\zip.php:4
>=> TRUE
0.0036 105224 +16 -> ZipArchive->addFile('test.txt') G:\www\myweb\php\test\zip.php:5
>=> TRUE
0.0045 105176 -48 -> var_dump(class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 1; public $filename = 'G:\\www\\myweb\\php\\test\\test.zip'; public $comment = '' }) G:\www\myweb\php\test\zip.php:6
>=> NULL
0.0050 105200 +24 -> ZipArchive->close() G:\www\myweb\php\test\zip.php:7
>=> TRUE
>=> 1
1.2511 zu
TRACE END [2011-11-28 02:59:41]

从上图看到,在zip.php 第5行,返回值是TRUE的!

再看下,test.txt不存在的情况:

TRACE START [2011-11-28 03:02:48]
0.0015 104000 +104000 -> {main}() G:\www\myweb\php\test\zip.php:0
=> $zip = class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 0; public $filename = ''; public $comment = '' } G:\www\myweb\php\test\zip.php:2
0.0018 105136 +1136 -> var_dump(class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 0; public $filename = ''; public $comment = '' }) G:\www\myweb\php\test\zip.php:3
>=> NULL
0.0022 105208 +72 -> ZipArchive->open('test.zip', 1) G:\www\myweb\php\test\zip.php:4
>=> TRUE
0.0028 105224 +16 -> ZipArchive->addFile('testno.txt') G:\www\myweb\php\test\zip.php:5
>=> TRUE
0.0033 105176 -48 -> var_dump(class ZipArchive { public $status = 0; public $statusSys = 0; public $numFiles = 1; public $filename = 'G:\\www\\myweb\\php\\test\\test.zip'; public $comment = '' }) G:\www\myweb\php\test\zip.php:6
>=> NULL
0.0035 105200 +24 -> ZipArchive->close() G:\www\myweb\php\test\zip.php:7
>=> FALSE
>=> 1
0.8266 zu
TRACE END [2011-11-28 03:02:48]

同样在zip.php 第5行,返回值也是TRUE的!!!注意整个程序并没有报什么文件不存在的错误信息。

不过对比2张图,可以看出在zip.php程序第7行有不同,返回值是FALSE,很关键!

问题答案:

看了下php官网,查了下,看到如下信息:

john factorial 29-Dec-2010 08:58
If you're adding multiple files to a zip and your $zip->close() call is returning FALSE, ensure that all the files you added actually exist. Apparently $zip->addFile() returns TRUE even if the file doesn't actually exist. It's a good idea to check each file with file_exists() or is_readable() before calling $zip->addFile() on it.

大致意思是:当你使用addFile添加到zip包时,必须确保你添加的文件是存在的,否则close时 会返回FALSE,而且,使用addFile时,即使文件不存在也会返回TRUE的!!!

解决:

所以更严谨的做法 应该这样:

 1 <?php
2 function zipWrapper($fileToZip){
3 $zip = new ZipArchive;
4 if ($zip -> open($fileToZip,ZIPARCHIVE::CREATE) === TRUE) {
5 if(file_exists($fileToZip)){
6 $zip->addFile($fileToZip);
7 }
8 if($zip -> close()){
9 return true;
10 }else{
11 return false;
12 }
13 } else {
14 return false;
15 }
16 }
17 ?>

参考资料:

php官网 ZipArchive::close() 评论