常用的方法
php ZipArchive可以说是php自带的一个函数了,他可对对文件进行压缩与解压缩处理,但是使用此类之前我们必须在php.ini中把extension=php_zip.dll前面的分号有没有去掉,然后再重启Apache这样才能使用这个类库。
ziparchive 可选参数,更多的使用例子,参考PHP - Manual: ZipArchive - 互联网笔记
ZipArchive::addEmptyDir
添加一个新的文件目录
<?php
$zip = new ZipArchive;
if ($zip->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
<?php
$zip = new ZipArchive;
$res = $zip->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';
}
?>
<?php
$name = tempnam(sys_get_temp_dir(), "FOO");
$zip = new ZipArchive;
$res = $zip->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));
浏览器下载并删除压缩文件
以下是打包服务器上某个文件夹中所有文件,并下载的然后再删除压缩文件的全部代码:
<?php
$STATICS_PATH = PATH['statics'];
$templatePath = '2023/03/0d9cf19188485dc70e21a1aae4ffad8d';
$finalPath = "{$STATICS_PATH}/templates-packages/{$templatePath}";
if(!file_exists($finalPath)) {exit('路径不存在');
}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 { // 将文件加入zip对象 传入第二个参数是避免出现目录层级的问题$zip->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类使用实例详解