php 压缩多文件并且打包zip包下载
最近项目有一个需求:用户勾选多个文件,点击‘批量下载’,可以将多个文件打包成一个zip包下载到用户本地。我们来看看如何实现。
- ZipArchive函数类
要实现打包功能,首先要确定自己的php是否支持已经安装了ZipArchive 扩展,如果没有安装,请自行安装本扩展。ps:php7.0+已经默认安装了该扩展,您无需做任何配置即可使用。 - 实现思路
首先我们把需求拆分,当用户点击‘批量下载’,即将多个文件打包成zip下载到本地。那么我们设计的时候其实是这样的:
- 获取用户选择的文件id.并且得到其物理路径。
- 选择出文件,并且压缩成零时压缩包。
- 下载压缩包
- 删除压缩包
从上面可以看到,获取文件的物理路径至关重要,因为要从众多的文件中选出,所以设计上传的路径很关键。我的项目使用的是laravel框架,上传路径为/public/upload/file/attendence。
可以看到,如果把文件归置在一个文件夹中,那么只需要打开一次文件夹即可。很多时候,程序员习惯把文件上传的目录设置为/**/年-月-日/这样的格式,那么想一想,在这个需求中,如果是按时间来生成目录,如果用户勾选了一个月的文件下载,那么就要打开至少30次文件夹,非常消耗资源。
下面我们直接来看代码:
function zipAndDownLoad($files=[],$type=1)
{
$folder_name = $type == 1 ? "uploads/file/contact/zip/" :"uploads/file/attendence/zip/";
$true_path = public_path($folder_name);
//这里需要注意该目录是否存在,并且有创建的权限
$zipname = $true_path.time().'.zip';
//这是要打包的文件地址数组
if($files)
{
foreach($files as $k=>$v)
{
$files[$k] = public_path($v);
}
$zip = new \ZipArchive();
$res = $zip->open($zipname, \ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($files as $file) {
//这里直接用原文件的名字进行打包,也可以直接命名,需要注意如果文件名字一样会导致后面文件覆盖前面的文件,所以建议重新命名
$new_filename = substr($file, strrpos($file, '/') + 1);
$zip->addFile($file, $new_filename);
}
}
//关闭文件
$zip->close();
ob_end_clean();
$info = response()->download($zipname);
return $info;
}
return 0;
}