php调用nginx的mod_zip模块打包ZIP文件
php本身有zip模块,可以生产zip文件。但是这个zip模块只能使用本地文件来打包。如果需要打包输出的文件来自网络,就得先保存临时文件。在文件数量多或者文件大的时候就很杯具。另外,由php来输出大的打包文件会占用php进程大量时间,影响并发能力。
nginx有一个第三方模块,mod_zip。同样可以输出zip包。和X-Accel-Redirect有点类似,只需要php输出相应文件的路径等信息,然后给一个特殊的响应头即可。
nginxzip模块使用的响应头是X-Archive-Files:zip。加上这个响应头,nginxzip模块就会处理响应正文,完成打包输出。
比如:
printf("%s%d%s%s\n",$crc32,$size,$url,$path);
逐条输出要打包的文件。
$crc32是16进制的文件crc32值。也可以不提供,用“-”代替。不过这样就没法用Range分块下载,断点续传了。
$size是文件大小的十进制整数。
$url是要打包的源地址。如果要打包一个本地文件,可以先在nginx中做一个internalpath。
$path是zip包中的路径。
不过这样没法创建空目录。一方面,zip格式开始就没有定义空目录,后来的标准和软件都是通过加一个/结尾的0大小文件来实现的。这时,就需要先在nginx中做一个internal的0大小文件,比如位于/_0。然后输出
printf("%s%d%s%s\n",'00000000',0,'/_0',$path.'/');
如果要支持中文路径,可以使用X-Archive-Charset:utf8这样的响应头,内容为你输出的编码。nginxzip模块会按标准转换成utf8的标准格式。不过各个软件对这个zip的标准支持不一,比如windows的zip目录就不支持,只能以gbk编码直接输出。其他软件对编码支持效果也各不相同。测试过的winrar,7zip,windowszip目录中,winrar倒是都可以很好支持。7zip可能会把部分中文空目录变成0大小文件。所以,这点还需要自己斟酌处理。