常用的方法

php ZipArchive可以说是php自带的一个函数了,他可对对文件进行压缩与解压缩处理,但是使用此类之前我们必须在php.ini中把extension=php_zip.dll前面的分号有没有去掉,然后再重启Apache这样才能使用这个类库。

ziparchive 可选参数,更多的使用例子,参考PHP – Manual: ZipArchive – 互联网笔记

ZipArchive::addEmptyDir

添加一个新的文件目录

open('test.zip') === TRUE) {if($zip->addEmptyDir('newDirectory')) {echo 'Created a new root directory';} else {echo 'Could not create the directory';}$zip->close();} else {echo 'failed';}?>

ZipArchive::addFile

将文件添加到指定zip压缩包中。

ZipArchive::addFromString

添加的文件同时将内容添加进去

ZipArchive::close

关闭ziparchive

ZipArchive::extractTo

将压缩包解压

ZipArchive::open

打开一个zip压缩包

ZipArchive::getStatusString

返回压缩时的状态内容,包括错误信息,压缩信息等等

ZipArchive::deleteIndex

删除压缩包中的某一个文件,如:deleteIndex(0)删除第一个文件

ZipArchive::deleteName

删除压缩包中的某一个文件名称,同时也将文件删除。

ZipArchive::open

open('test.zip', ZipArchive::CREATE);if ($res === TRUE) {$zip->addFromString('test.txt', 'file content goes here');$zip->addFile('data.txt', 'entryname.txt');$zip->close();echo 'ok';} else {echo 'failed';}?>

open($name, ZipArchive::OVERWRITE); /* truncate as empty file is not valid */if ($res === TRUE) {$zip->addFile('data.txt', 'entryname.txt');$zip->close();echo 'ok';} else {echo 'failed';}?>

基本使用例

解压缩zip文件

注意,解压的文件夹中不要有中文!会引起乱码!

$zip = new ZipArchive;//新建一个ZipArchive的对象/*通过ZipArchive的对象处理zip文件$zip->open这个方法的参数表示处理的zip文件名。如果对zip文件对象操作成功,$zip->open这个方法会返回TRUE*/if ($zip->open('test.zip')){$zip->extractTo('images');//假设解压缩到在当前路径下images文件夹的子文件夹php$zip->close();//关闭处理的zip文件}

文件追加内容添加到zip文件

zip = new ZipArchive;$res = $zip->open('test.zip', ZipArchive::CREATE);if ($res) {$zip->addFromString('test.txt', 'file content goes here');$zip->close();echo 'ok';} else {echo 'failed';}

建议:$zip->open 使用try-catch去捕捉

try { $zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);//关闭处理的zip文件$zip->close();}catch (Exception $e) {exit( $e->getMessage());}

将服务器上的文件夹打包成zip文件

function addFileToZip($path, $zip) {$handler = opendir($path); //打开当前文件夹由$path指定。/*循环的读取文件夹下的所有文件和文件夹其中$filename = readdir($handler)是每次循环的时候将读取的文件名赋值给$filename,为了不陷于死循环,所以还要让$filename !== false。一定要用!==,因为如果某个文件名如果叫'0',或者某些被系统认为是代表false,用!=就会停止循环*/while (($filename = readdir($handler)) !== false) {//文件夹文件名字为'.'和‘..’,不要对他们进行操作if ($filename != "." && $filename != "..") {$filePath = "{$path}/{$filename}";// 如果读取的某个对象是文件夹,则递归if (is_dir($filePath)) {addFileToZip($filePath, $zip);} else { var_dump($filePath);// 将文件加入zip对象 传入第二个参数是避免出现目录层级的问题$zip->addFile($filePath, pathinfo($filePath, PATHINFO_BASENAME));}}}@closedir($path);}$STATICS_PATH = 'd:/xampp/htdocs/xin-card';$templatePath = '2023/03/0d9cf19188485dc70e21a1aae4ffad8d';// 要下载文件的最终目录$finalPath = "{$STATICS_PATH}/templates/{$templatePath}";if(!file_exists($finalPath)) {exit('路径不存在');}$zip = new ZipArchive();$zipName = time() . '.zip';// d:/xampp/htdocs/xin-card/zip/187823213.zip$zipPath = "{$STATICS_PATH}/zip/{$zipName}";try {$zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);//调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法addFileToZip($finalPath, $zip); //关闭处理的zip文件$zip->close();}catch (Exception $e) {exit( $e->getMessage());}

解决生成压缩文件带有目录层级的问题

比如上面的addFileToZip方法,我一开始是这么写的:

if (is_dir($filePath)) { addFileToZip($filePath, $zip);} else {$zip->addFile($filePath);}

这样写最终导致的后果就是生成的压缩文件,里面带有目录层级!

像这样:D:\xampp\htdocs\xin-card\statics\templates-packages\1679986315\D_\xampp\htdocs\xin-card\statics\templates-packages\2023\03\0d9cf19188485dc70e21a1aae4ffad8d

实际上只有最后的文件夹才是我想要的!

如果你使用php ZipArchive addFile 方法把多个文件压缩在1个目录时会产生一个问题,我们只想要在当前目录把所有文件放在一起,结果他安装每个文件的所在目录在当前目录创建一遍,解决方式如下:

$allAttachment = ['1.png', '2.png', '3.png', '4.png',];// 循环保存文件到Zip中foreach ($allAttachment as $attachmentItem) {$rootpath = 'd:/xampp/htdocs/xin-cards/';if ($attachmentItem) {$attachmentItem = "$rootpath/$attachmentItem";// 添加文件$zip->addFile($attachmentItem);// 对添加的文件重新命名,避免出现目录问题$zip->renameName($attachmentItem, basename($attachmentItem));}}// 关闭$zip->close();如果不能解决您的问题,可以尝试如下方式// 添加文件$zip->addFile($attachmentItem, pathinfo($attachmentItem, PATHINFO_BASENAME));

浏览器下载并删除压缩文件

以下是打包服务器上某个文件夹中所有文件,并下载的然后再删除压缩文件的全部代码:

addFile($filePath, pathinfo($filePath, PATHINFO_BASENAME));}}}@closedir($path);}$zip = new ZipArchive();$zipName = time() . '.zip';$zipPath = "{$STATICS_PATH}/templates-packages/{$zipName}";try {$zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);//调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法addFileToZip($finalPath, $zip); //关闭处理的zip文件$zip->close();//下载文件$file = fopen($zipPath, "r");//返回的文件类型Header("Content-type: application/octet-stream");//按照字节大小返回Header("Accept-Ranges: bytes");//返回文件的大小Header("Accept-Length: " . filesize($zipPath));//这里设置客户端的弹出对话框显示的文件名Header("Content-Disposition: attachment; filename=" . $zipName);//一次性将数据传输给客户端//echo fread($file, filesize($filePath));//一次只传输1024个字节的数据给客户端//向客户端回送数据$buffer = 1024;////判断文件是否读完while (!feof($file)) {//将文件读入内存$file_data = fread($file, $buffer);//每次向客户端回送1024个字节的数据echo $file_data; }//将生成的zip文件在服务器端删除,只需要客户端下载就行了@unlink($zipPath);}catch (Exception $e) {exit( $e->getMessage());}

相关资料

解决phpZipArchive生成压缩文件带有目录层级的问题【阿里开发者社区】

解决phpZipArchive生成压缩文件带有目录层级的问题

php开启ziparchivephpZipArchive类使用实例详解