<?php
namespace app\lib;
/**
* 压缩包驱动
* @author Wmeng
* @version 0.0.1
*/
class ZipHelper
{
protected $zip;
protected $root;
protected $ignored_names;
/**
* 构造函数
*/
public function __construct()
{
$this->zip = new \ZipArchive();
}
/**
* 解压zip文件到指定文件夹
* @desc description
* @param [string] $zipfile [压缩文件路径]
* @param [string] $path [压缩包解压到的目标路径]
* @return [boolean] [true | false]
*/
public function Unzip($zipfile, $path)
{
if($this->zip->open($zipfile) === true)
{
$file_tmp = @fopen($zipfile, "rb");
$bin = fread($file_tmp, 15); //只读15字节 各个不同文件类型,头信息不一样。
fclose($file_tmp);
/* 只针对zip的压缩包进行处理 */
if(true === $this->GetTypeList($bin))
{
$result = $this->zip->extractTo($path);
$this->zip->close();
return $result;
}
}
return false;
}
public function zipFile($file, $zippath)
{
//$zip_time = time().".zip"; // 压缩的文件名
$zip_filename = $zippath; // 指定一个压缩包地址
// 打开压缩包,没有则创建
if($this->zip->open($zip_filename, \ZipArchive::CREATE) !== true)
{
throw new Exception("cannot open <$zip_filename>\n");
}
// 参数1是要压缩的文件,参数2为压缩后,在压缩包中的文件名「这里我们把 demo1.php 文件压缩,压缩后的文件为 dd.php」,如果需要的压缩后的文件跟原文件名一样 addFile() 的第二个参数可以改为 basename("../alg/demo1.php"),也就是原文件所在的路径
$this->zip->addFile($file,basename($file));
return $this->zip->close();
}
/**
* 创建压缩文件夹
* @desc description
* @param [string] $zipfile [将要生成的压缩文件路径]
* @param [string] $folder [将要被压缩的文件夹路径]
* @param [string] $ignored [要忽略的文件列表]
* @return [boolean] [true | false]
*/
public function ZipFolder($zipfile, $folder, $ignored = null)
{
$this->ignored_names = is_array($ignored) ? $ignored : ($ignored ? array($ignored) : array());
if($this->zip->open($zipfile, \ZipArchive::CREATE) !== true)
{
throw new \Exception("cannot open <$zipfile>\n");
}
$folder = substr($folder, -1) == '/' ? substr($folder, 0, strlen($folder)-1) : $folder;
if(strstr($folder, '/'))
{
$this->root = substr($folder, 0, strrpos($folder, '/')+1);
$folder = substr($folder, strrpos($folder, '/')+1);
}
$this->CreateZip($folder);
return $this->zip->close();
}
/**
* 递归添加文件到压缩包
* @desc description
* @param [string] $folder [添加到压缩包的文件夹路径]
* @param [string] $parent [添加到压缩包的文件夹上级路径]
*/
private function CreateZip($folder, $parent = null)
{
$full_path = $this->root . $parent . $folder;
$zip_path = $parent . $folder;
$this->zip->addEmptyDir($zip_path);
$dir = new \DirectoryIterator($full_path);
foreach($dir as $file)
{
if(!$file->isDot())
{
$filename = $file->getFilename();
if(!in_array($filename, $this->ignored_names))
{
if($file->isDir())
{
$this->CreateZip($filename, $zip_path.'/');
} else {
$this->zip->addFile($full_path.'/'.$filename, $zip_path.'/'.$filename);
}
}
}
}
}
/**
* 读取压缩包文件与目录列表
* @desc description
* @param [string] $zipfile [压缩包文件]
* @return [array] [文件与目录列表]
*/
public function FileList($zipfile)
{
$file_dir_list = array();
$file_list = array();
if($this->zip->open($zipfile) == true)
{
for ($i = 0; $i < $this->zip->numFiles; $i++)
{
$numfiles = $this->zip->getNameIndex($i);
if(preg_match('/\/$/i', $numfiles))
{
$file_dir_list[] = $numfiles;
} else {
$file_list[] = $numfiles;
}
}
}
return array('files'=>$file_list, 'dirs'=>$file_dir_list);
}
/**
* 得到文件头与文件类型映射表
* @desc description
* @param [string] $bin [文件的二进制前一段字符]
* @return [boolean] [true | false]
*/
private function GetTypeList($bin)
{
$array = array(
array("504B0304", "zip")
);
foreach($array as $v)
{
$blen = strlen(pack("H*", $v[0])); //得到文件头标记字节数
$tbin = substr($bin, 0, intval($blen)); ///需要比较文件头长度
if(strtolower($v[0]) == strtolower(array_shift(unpack("H*", $tbin))))
{
return true;
}
}
return false;
}
}
?>
用例:
public function download(){
$signer_list_id = abs((int)Request::param('signer_list_id',0));
$signer_info = Db::table('bq_contract_doc_signers')->where('id',$signer_list_id)
->field('system_sn,signer_mobile,status,sign_status,esign_flow_id')->find();
if(!$signer_info){
throw new ParameterException(['msg'=>'信息错误']);
}
//用户id
$user_id = Request::middleware('client_user_id');
//获取用户手机号
$signer_mobile = Db::table('bq_user')->where('id',$user_id)->value('username');
if($signer_mobile != $signer_info['signer_mobile']){
throw new ParameterException(['msg'=>'您无权限操作']);
}
//打包忽略的文件列表
$ignored_arr = [];
//将要打包生成的压缩文件路径
$downfilepath = str_replace('\\', '/', public_path()."storage/{$signer_info['system_sn']}/合同文件.zip");
if (file_exists($downfilepath)) {
@unlink($downfilepath);
}
//将要被打包压缩的文件夹路径
$pack_path = str_replace('\\', '/', public_path()."storage/{$signer_info['system_sn']}/合同文件/");
$zip_helper = new ZipHelper();
$res = $zip_helper->ZipFolder($downfilepath,$pack_path,$ignored_arr);
if($res){
return get_domain()."/storage/{$signer_info['system_sn']}/合同文件.zip";
}else{
return false;
}
}