常用的方法
php ZipArchive可以说是php自带的一个函数了,他可对对文件进行压缩与解压缩处理,但是使用此类之前我们必须在php.ini中把extension=php_zip.dll前面的分号有没有去掉,然后再重启Apache这样才能使用这个类库。
ziparchive 可选参数,更多的使用例子,参考PHP - Manual: ZipArchive - 互联网笔记
ZipArchive::addEmptyDir
添加一个新的文件目录
php
<?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
<?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
<?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文件
注意,解压的文件夹中不要有中文!会引起乱码!
php
$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文件
php
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去捕捉
php
try {
$zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
//关闭处理的zip文件
$zip->close();
} catch (Exception $e) {
exit( $e->getMessage());
}
将服务器上的文件夹打包成zip文件
php
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方法,我一开始是这么写的:
php
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个目录时会产生一个问题,我们只想要在当前目录把所有文件放在一起,结果他安装每个文件的所在目录在当前目录创建一遍,解决方式如下:
php
$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
<?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生成压缩文件带有目录层级的问题【阿里开发者社区】