您現在的位置是:首頁 > 垂釣

PHP支援多格式的解壓縮工具類

  • 由 博讀程式碼 發表于 垂釣
  • 2021-12-22
簡介安裝p7zip p7zip-full軟體:用於解壓縮7z格式檔案​四、實現class ZipUtil{** * 解壓 * @param string $zipFilePath 壓縮檔案路徑 * @param

如何解壓7z壓縮包

一、引語

本人在做一個企業雲盤專案當中,遇到一個檔案線上解壓縮的需求,查了網上很多資料,但都是隻支援單一格式或部分格式。因此建立了本工具類,對市面上主流的壓縮格式進行整合支援,並且簡單易用。

PHP支援多格式的解壓縮工具類

二、功能

​1。支援zip、rar、phar、tar、gz、bz2、7z格式的解壓;

2。支援對單檔案、多檔案、資料夾進行壓縮成zip檔案格式資料庫連線池。​

​​

三、前置條件

​1。 安裝php_zip外掛:用於解壓縮zip格式檔案

2。 安裝php_rar外掛:用於解壓縮rar格式檔案

3。 安裝php_phar外掛:用於解壓縮phar、tar、gz、bz2格式檔案

4。 安裝p7zip p7zip-full軟體:用於解壓縮7z格式檔案​

四、實現

class ZipUtil{ /** * 解壓 * @param string $zipFilePath 壓縮檔案路徑 * @param string $toDirPath 解壓目錄路徑 * @return string * @throws \Exception */ public static function extract(string $zipFilePath, string $toDirPath) { $toDirPath = rtrim($toDirPath, ‘/’); self::deleteDir($toDirPath, false); if (!is_file($zipFilePath)) throw new \Exception(‘檔案不存在。’); if (!is_dir($toDirPath)) { mkdir($toDirPath, 0777, true); } $zipFilePathInfo = pathinfo($zipFilePath); $zipExt = pathinfo($zipFilePath, PATHINFO_EXTENSION); switch ($zipExt) { case ‘zip’: if (!class_exists(‘\ZipArchive’)) throw new \Exception(‘未安裝Zip外掛。’); $zipArch = new \ZipArchive(); if ($zipArch->open($zipFilePath) !== true) throw new \Exception(‘解壓失敗。’); //$zipArch->extractTo($toDirPath); //這個中文會亂碼 //解決中文會亂碼 $fileNum = $zipArch->numFiles; for ($i = 0; $i < $fileNum; ++$i) { $statInfo = $zipArch->statIndex($i, \ZipArchive::FL_ENC_RAW); $statInfo[‘name’] = self::convertToUtf8($statInfo[‘name’]); //print_r($statInfo); if ($statInfo[‘crc’] === 0 && $statInfo[‘name’][strlen($statInfo[‘name’]) - 1] === ‘/’) { $dirPath = $toDirPath 。 ‘/’ 。 $statInfo[‘name’]; if (!is_dir($dirPath)) { mkdir($dirPath, 0777, true); } } else { copy(‘zip://’ 。 $zipFilePath 。 ‘#’ 。 $zipArch->getNameIndex($i), $toDirPath 。 ‘/’ 。 $statInfo[‘name’]); } } $zipArch->close(); break; case ‘rar’: if (!class_exists(‘\RarArchive’)) throw new \Exception(‘未安裝Rar外掛。’); $rarArch = \RarArchive::open($zipFilePath); if ($rarArch === false) throw new \Exception(‘解壓失敗。’); $entries = $rarArch->getEntries(); if ($entries === false) throw new \Exception(‘解壓失敗。’); foreach ($entries as $entry) { $entry->extract($toDirPath); } $rarArch->close(); break; case ‘phar’: if (!class_exists(‘\Phar’)) throw new \Exception(‘未安裝Phar外掛。’); $phar = new \Phar($zipFilePath, null, null); $extract = $phar->extractTo($toDirPath, null, true); if (!isset($zipFilePathInfo[‘extension’])) { unlink($zipFilePath); } if ($extract === false) throw new \Exception(‘解壓失敗。’); break; case ‘tar’: case ‘gz’: case ‘bz2’: if (!class_exists(‘\PharData’)) throw new \Exception(‘未安裝Phar外掛。’); $formats = [ ‘tar’ => \Phar::TAR, ‘gz’ => \Phar::GZ, ‘bz2’ => \Phar::BZ2, ]; $format = $formats[$zipExt]; $phar = new \PharData($zipFilePath, null, null, $format); $extract = $phar->extractTo($toDirPath, null, true); if (!isset($zipFilePathInfo[‘extension’])) { unlink($zipFilePath); } if ($extract === false) throw new \Exception(‘解壓失敗。’); break; case ‘7z’: if(shell_exec(‘type 7z’) === null) throw new \Exception(‘未安裝p7zip軟體。’); $cmd = ‘7z x ’ 。 $zipFilePath 。 ‘ -r -o’ 。 $toDirPath; $result = shell_exec($cmd); break; default: throw new \Exception(‘不支援的解壓格式。’); } return $toDirPath; } /** * 壓縮多個檔案 * @param array $files 檔案列表,格式:[[‘file_type’=>‘file|folder’, ‘file_path’=>‘/a/b/test。txt’, ‘local_name’=>‘b/test。txt’]] * @param string $toFilePath 壓縮檔案路徑 * @return string * @throws \Exception */ public static function package(array $files, string $toFilePath) { $toFilePathInfo = pathinfo($toFilePath); if (!is_dir($toFilePathInfo[‘dirname’])) { mkdir($toFilePathInfo[‘dirname’], 0777, true); } $zipArch = new \ZipArchive(); if ($zipArch->open($toFilePath, \ZipArchive::CREATE) !== true) throw new \Exception(‘壓縮失敗。’); foreach ($files as $file) { if ($file[‘file_type’] === ‘folder’) { $zipArch->addEmptyDir(ltrim($file[‘local_name’], ‘/’)); } else if ($file[‘file_type’] === ‘file’) { if (is_file($file[‘file_path’])) { $zipArch->addFile($file[‘file_path’], $file[‘local_name’]); } } } $zipArch->close(); return $toFilePath; } /** * 壓縮資料夾 * @param string $dirPath 要壓縮的資料夾路徑 * @param string $toFilePath 壓縮檔案路徑 * @param bool $includeSelf 是否包含自身 * @return string * @throws \Exception */ public static function packageDir(string $dirPath, string $toFilePath, bool $includeSelf = true) { if (!is_dir($dirPath)) throw new \Exception(‘資料夾不存在。’); $toFilePathInfo = pathinfo($toFilePath); if (!is_dir($toFilePathInfo[‘dirname’])) { mkdir($toFilePathInfo[‘dirname’], 0777, true); } $dirPathInfo = pathinfo($dirPath); //print_r($dirPathInfo); $zipArch = new \ZipArchive(); if ($zipArch->open($toFilePath, \ZipArchive::CREATE) !== true) throw new \Exception(‘壓縮失敗。’); $dirPath = rtrim($dirPath, ‘/’) 。 ‘/’; $filePaths = self::scanDir($dirPath); if ($includeSelf) { array_unshift($filePaths, $dirPath); } //print_r($filePaths); foreach ($filePaths as $filePath) { $localName = mb_substr($filePath, mb_strlen($dirPath) - ($includeSelf ? mb_strlen($dirPathInfo[‘basename’]) + 1 : 0)); //echo $localName 。 PHP_EOL; if (is_dir($filePath)) { $zipArch->addEmptyDir($localName); } else if (is_file($filePath)) { $zipArch->addFile($filePath, $localName); } } $zipArch->close(); return $toFilePath; } /** * 壓縮單個檔案 * @param string $filePath 要壓縮的檔案路徑 * @param string $toFilePath 壓縮檔案路徑 * @return string * @throws \Exception */ public static function packageFile(string $filePath, string $toFilePath) { if (!is_file($filePath)) throw new \Exception(‘檔案不存在。’); $toFilePathInfo = pathinfo($toFilePath); if (!is_dir($toFilePathInfo[‘dirname’])) { mkdir($toFilePathInfo[‘dirname’], 0777, true); } $filePathInfo = pathinfo($filePath); $zipArch = new \ZipArchive(); if ($zipArch->open($toFilePath, \ZipArchive::CREATE) !== true) throw new \Exception(‘壓縮失敗。’); $zipArch->addFile($filePath, $filePathInfo[‘basename’]); $zipArch->close(); return $toFilePath; } /** * 字串轉為UTF8字符集 * @param string $str * @return false|string */ private static function convertToUtf8(string $str) { $charset = mb_detect_encoding($str, [‘UTF-8’, ‘GBK’, ‘BIG5’, ‘CP936’]); if ($charset !== ‘UTF-8’) { $str = iconv($charset, ‘UTF-8’, $str); } return $str; } /** * 刪除目錄以及子目錄等所有檔案 * * - 請注意不要刪除重要目錄! * * @param string $path 需要刪除目錄路徑 * @param bool $delSelf 是否刪除自身 */ private static function deleteDir(string $path, bool $delSelf = true) { if (!is_dir($path)) { return; } $dir = opendir($path); while (false !== ($file = readdir($dir))) { if (($file != ‘。’) && ($file != ‘。。’)) { $full = $path 。 ‘/’ 。 $file; if (is_dir($full)) { self::deleteDir($full, true); } else { unlink($full); } } } closedir($dir); if ($delSelf) { rmdir($path); } } /** * 遍歷資料夾,返回檔案路徑列表 * @param string $path * @param string $fileType all|file|folder * @param bool $traversalChildren 是否遍歷下級目錄 * @return array */ private static function scanDir(string $path, string $fileType = ‘all’, bool $traversalChildren = true) { if (!is_dir($path) || !in_array($fileType, [‘all’, ‘file’, ‘folder’])) { return []; } $path = rtrim($path, ‘/’); $list = []; $files = scandir($path); foreach ($files as $file) { if ($file != ‘。’ && $file != ‘。。’) { $p = $path 。 ‘/’ 。 $file; $isDir = is_dir($p); if ($isDir) { $p 。= ‘/’; } if ($fileType === ‘all’ || ($fileType === ‘file’ && !$isDir) || ($fileType === ‘folder’ && $isDir)) { $list[] = $p; } if ($traversalChildren && $isDir) { $list = array_merge($list, self::scanDir($p, $fileType, $traversalChildren)); } } } return $list; }}1。2。3。4。5。6。7。8。9。10。11。12。13。14。15。16。17。18。19。20。21。22。23。24。25。26。27。28。29。30。31。32。33。34。35。36。37。38。39。40。41。42。43。44。45。46。47。48。49。50。51。52。53。54。55。56。57。58。59。60。61。62。63。64。65。66。67。68。69。70。71。72。73。74。75。76。77。78。79。80。81。82。83。84。85。86。87。88。89。90。91。92。93。94。95。96。97。98。99。100。101。102。103。104。105。106。107。108。109。110。111。112。113。114。115。116。117。118。119。120。121。122。123。124。125。126。127。128。129。130。131。132。133。134。135。136。137。138。139。140。141。142。143。144。145。146。147。148。149。150。151。152。153。154。155。156。157。158。159。160。161。162。163。164。165。166。167。168。169。170。171。172。173。174。175。176。177。178。179。180。181。182。183。184。185。186。187。188。189。190。191。192。193。194。195。196。197。198。199。200。201。202。203。204。205。206。207。208。209。210。211。212。213。214。215。216。217。218。219。220。221。222。223。224。225。226。227。228。229。230。231。232。233。234。235。236。237。238。239。240。241。242。243。244。245。246。247。248。249。250。251。252。253。254。255。256。257。258。259。260。261。262。263。264。265。266。267。268。269。270。271。272。273。274。275。276。277。278。279。280。281。282。283。284。285。286。287。288。289。290。291。292。293。294。295。296。297。298。299。300。301。302。303。304。305。306。307。308。309。310。311。312。313。314。315。316。317。318。319。320。321。322。323。324。325。326。327。328。329。330。331。332。333。334。335。336。337。338。339。340。341。342。343。344。345。346。347。348。349。350。351。352。353。354。355。356。357。358。359。360。361。362。363。364。365。366。367。368。369。370。371。372。373。374。375。376。377。378。379。380。381。382。383。384。385。386。387。388。389。390。391。392。393。394。395。396。397。398。399。400。401。402。403。404。405。406。407。408。409。410。411。412。413。414。415。416。417。418。419。420。421。422。423。424。425。426。427。428。429。430。431。432。433。434。435。436。437。438。439。440。441。442。443。444。445。446。447。448。449。450。451。452。453。454。455。456。457。458。459。460。461。462。463。464。465。466。467。468。469。470。471。472。473。474。475。476。477。478。479。480。481。482。483。484。485。486。487。488。489。490。491。492。493。494。495。496。497。498。499。500。501。502。503。504。505。506。507。508。509。510。511。512。513。514。515。516。517。518。519。520。521。522。523。524。525。526。527。528。529。530。531。532。533。534。535。536。537。538。539。540。541。542。543。544。545。546。547。548。549。550。551。552。553。554。555。556。557。558。559。560。561。562。563。564。565。

呼叫:

//示例1:解壓zip檔案到/test/test1/目錄下ZipUtil::extract(‘/test/test1。zip’, ‘/test/test1/’);//示例2:解壓rar檔案到/test/test2/目錄下ZipUtil::extract(‘/test/test2。rar’, ‘/test/test2/’);//示例3:解壓phar檔案到/test/test3/目錄下ZipUtil::extract(‘/test/test3。phar’, ‘/test/test3/’);//示例4:解壓tar檔案到/test/test4/目錄下ZipUtil::extract(‘/test/test4。tar’, ‘/test/test4/’);//示例5:解壓gz檔案到/test/test5/目錄下ZipUtil::extract(‘/test/test5。tar。gz’, ‘/test/test5/’);//示例6:解壓bz2檔案到/test/test6/目錄下ZipUtil::extract(‘/test/test6。tar。bz2’, ‘/test/test6/’);//示例7:解壓7z檔案到/test/test7/目錄下ZipUtil::extract(‘/test/test7。7z’, ‘/test/test7/’);//示例8:壓縮單個檔案ZipUtil::packageFile(‘/test/test8/1。txt’, ‘/test/test8。zip’);//示例9:壓縮多個檔案ZipUtil::package([ [‘file_type’=>‘file’, ‘file_path’=>‘/test/test9/1。txt’, ‘local_name’=>‘1。txt’], [‘file_type’=>‘file’, ‘file_path’=>‘/test/test9/2。txt’, ‘local_name’=>‘2。txt’], [‘file_type’=>‘folder’, ‘local_name’=>‘1/’], [‘file_type’=>‘folder’, ‘local_name’=>‘2/’],], ‘/test/test9。zip’);//示例10:壓縮資料夾ZipUtil::packageDir(‘/test/test10/’, ‘/test/test10。zip’);1。2。3。4。5。6。7。8。9。10。11。12。13。14。15。16。17。18。19。20。21。22。23。24。25。26。27。28。29。30。31。32。33。34。35。36。37。38。39。40。41。42。43。44。45。46。47。48。49。50。51。52。53。54。55。56。57。58。59。60。61。62。63。64。65。66。67。68。69。70。71。72。73。74。75。76。

五、結語

在剛開始使用這個工具類的過程中,發現在了個坑,就是在window壓縮的zip檔案放到linux進行解壓會發生檔名亂碼的情況,所以不能直接使用extractTo方法進行解壓,需要對zip解壓出來的檔名進行轉碼。

​以上是本期分享的全部內容,主要講解透過PHP對主流的壓縮格式進行整合支援,簡單易用。

下期會分享應用配置管理演變及apollo概念拆解哦,敬請期待~

​歡迎各位關注、留言,大家的支援就是我的動力!

Top