原文提供完整 class zip 手工解析 ZIP 二進位格式,支援:
get_List($zip_name):取得壓縮檔清單 (檔名、大小、CRC、修改時間、是否資料夾)Extract($zip_name, $to, $index):解壓指定項目或全部Add($files, $compact):建立壓縮檔 (支援 gzcompress)缺點:程式碼冗長、效能較低、中文檔名編碼處理需自行轉換 (ZIP 標準早期無編碼規定)。
<?php
class ZipHelper
{
/** 取得壓縮檔清單 */
public static function listArchive(string $zipPath): array
{
$zip = new ZipArchive();
if ($zip->open($zipPath) !== true) return [];
$list = [];
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$list[] = [
'name' => $stat['name'],
'size' => $stat['size'],
'comp_size' => $stat['comp_size'],
'crc32' => sprintf('%X', $stat['crc']),
'mtime' => $stat['mtime'],
'is_dir' => substr($stat['name'], -1) === '/',
];
}
$zip->close();
return $list;
}
/** 解壓縮 (支援密碼、中文檔名) */
public static function extract(string $zipPath, string $destDir, ?string $password = null): bool
{
$zip = new ZipArchive();
$res = $zip->open($zipPath);
if ($res !== true) return false;
if ($password !== null) {
$zip->setPassword($password);
}
// 確保目的目錄存在
if (!is_dir($destDir)) {
mkdir($destDir, 0777, true);
}
$success = $zip->extractTo($destDir);
$zip->close();
return $success;
}
/** 建立壓縮檔 */
public static function create(string $zipPath, string $sourceDir): bool
{
$zip = new ZipArchive();
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return false;
}
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
$relative = substr($file->getPathname(), strlen($sourceDir) + 1);
if ($file->isDir()) {
$zip->addEmptyDir($relative);
} else {
$zip->addFile($file->getPathname(), $relative);
}
}
return $zip->close();
}
}
?>
ZipArchive 內建支援 UTF-8 檔名 (需 ZIP 檔建立時使用 UTF-8 標誌)$name = iconv('CP950', 'UTF-8', $stat['name']); (視來源編碼調整)ZipArchive 或 7-Zip (`-mcu=on` 參數) 產生 UTF-8 編碼 ZIPclass zipPeter {
private $zip;
public function get_List($zip_name) { /* 使用 zip_open/zip_read/zip_close */ }
public function Extract($zip_name, $folder_name) { /* 同上 */ }
private function checkDirAndMk($dir, $mk=false, $mode=0777) { /* 遞迴建目錄 */ }
}
使用舊式 zip_* 函數族,功能受限,不建議新專案使用。