PHP zip压缩包操作类ZipArchive,解压文件、ZIPARCHIVE打包压缩文件夹、Zip压缩上传的多文件多图片
程序员文章站
2024-01-12 08:07:10
...
此类的原写法:https://www.php.cn/php-weizijiaocheng-405771.html,但是有问题的
使用之前要注意的点:
1、PHP7.2不需要另外添加zip扩展,如果其它版本,要注意有没有集成,没有集成就要下载
2、实例化zip类的时候$zip->open打开文件的时候,要使用ZipArchive::CREATE。我使用了ZIPARCHIVE::OVERWRITE 模式,而官方解释是“总是以一个新的压缩包开始,此模式下如果已经存在则会被覆盖。”。文档只说了存在的时候会覆盖,并没说不存在会创建(到底会不会创建,用了才知道),那我的使用场景是默认一定不存在这样一个文件的,那我把常亮改成CREATE试下,结果成功生成了zip文件。
3、路径问题,要使用相对路径,比如,./storage/uploads/XXXXX测试.zip,如果不行,自己根据使用的框架,自己测试换,这里用的是TP5.1,所以完整目录是在public下的storage文件夹
ZipFile类代码,可直接使用
<?php
/**
* Class ZipFile
* 压缩类
* @author connor
*/
class ZipFile
{
protected $zip;
protected $root;
protected $ignored_names;
public function __construct(){
$this->zip = new ZipArchive;
}
/**
* 解压zip文件到指定文件夹
* @access public
* @param string $zipfile 压缩文件路径
* @param string $path 压缩包解压到的目标路径
* @return booleam 解压成功返回 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;
}
else
{
return false;
}
}
return false;
}
/**
* 创建压缩文件
* @access public
* @param string $zipfile 将要生成的压缩文件路径
* @param strng $folder 将要被压缩的文件夹路径
* @param array $ignored 要忽略的文件列表
* @return booleam 压缩包生成成功返回true 否则返回 false
*/
public function zip ($zipfile, $folder, $ignored = null) {
$del_folder=$folder;
$this->ignored_names = is_array($ignored) ? $ignored : $ignored ? array($ignored) : array();
//这里要注意ZipArchive的写法,ZipArchive才没问题,前面new也是用ZipArchive,网上很多教程使用ZIPARCHIVE是错误的
//模式一定要用CREATE才能创建成功
$open_zip_bool=$this->zip->open($zipfile, ZipArchive::CREATE);
if ($open_zip_bool !== true) {
throw new Exception($this->message($open_zip_bool));
}
$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,null);
$zip_close=$this->zip->close();
$this->deleteFile($del_folder,true);//删除已被打包压缩的目录
return $zip_close;
}
/**
* 递归添加文件到压缩包
* @access private
* @param string $folder 添加到压缩包的文件夹路径
* @param string $parent 添加到压缩包的文件夹上级路径
* @return void
*/
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);
}
}
}
}
}
/**
* 读取压缩包文件与目录列表
* @access public
* @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);
}
/**
* 得到文件头与文件类型映射表
* @author wengxianhu
* @date 2013-08-10
* @param $bin string 文件的二进制前一段字符
* @return boolean
*/
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;
}
/**
+-----------------------------------------------------------------------------------------
* 删除目录及目录下所有文件或删除指定文件
+-----------------------------------------------------------------------------------------
* @param str $path 待删除目录路径
* @param int $delDir 是否删除目录,1或true删除目录,0或false则只删除文件保留目录(包含子目录)
+-----------------------------------------------------------------------------------------
* @return bool 返回删除状态
+-----------------------------------------------------------------------------------------
*/
public function deleteFile($path, $delDir = FALSE) {
if (is_array($path)) {
foreach ($path as $subPath)
deleteFile($subPath, $delDir);
}
if (is_dir($path)) {
$handle = opendir($path);
if ($handle) {
while (false !== ( $item = readdir($handle) )) {
if ($item != "." && $item != "..")
is_dir("$path/$item") ? deleteFile("$path/$item", $delDir) : unlink("$path/$item");
}
closedir($handle);
if ($delDir)
return rmdir($path);
}
} else {
if (file_exists($path)) {
return unlink($path);
} else {
return FALSE;
}
}
clearstatcache();
}
/**
* 对应打开文件失败的错误
* @author connor
* @param $code
* @return string
*/
public function message($code)
{
switch ($code)
{
case 0:
return '没有错误!';
case 1:
return '不支持多磁盘zip存档';
case 2:
return '重命名临时文件失败';
case 3:
return '关闭zip存档失败';
case 4:
return '寻求错误';
case 5:
return '读错误';
case 6:
return '写错误';
case 7:
return 'CRC错误';
case 8:
return '包含zip存档已关闭';
case 9:
return '文件不存在';
case 10:
return '文件已存在';
case 11:
return '无法打开文件';
case 12:
return '无法创建临时文件';
case 13:
return 'Zlib错误';
case 14:
return 'Malloc失败';
case 15:
return '参赛作品已被更改';
case 16:
return '不支持压缩方法';
case 17:
return 'Premature EOF';
case 18:
return 'Invalid argument';
case 19:
return '不是zip存档';
case 20:
return '内部错误';
case 21:
return 'Zip存档不一致';
case 22:
return '无法删除文件';
case 23:
return '条目已被删除';
default:
return '出现未知错误('.intval($code).')';
}
}
}
文件上传处理调用ZipFile类
//打包压缩文件
$zip_class=new \ZipFile();
$zip_file='./'.Config::get('app.upload_file').$zip_file_folder.'/'.$zip_name.'.zip';//不存在则创建$zip_name.zip文件
$zip_class->zip($zip_file,'./'.Config::get('app.upload_file').$folder);
上一篇: redis集群常见问题合集