PHP zip壓縮包操作類ZipArchive,解壓文件、ZIPARCHIVE打包壓縮文件夾、Zip壓縮上傳的多文件多圖片

此類的原寫法: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);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章