Windows 建立的 ZIP 檔,檔名編碼通常為 GBK/CP936;Linux PHP 環境預設 UTF-8,直接解壓會產生亂碼檔名。
<?php
$zip = zip_open('other.zip');
if (!$zip) die("無法開啟 ZIP");
while ($entry = zip_read($zip)) {
$size = zip_entry_filesize($entry);
// 關鍵:將檔名從 GBK 轉為 UTF-8
$name = iconv('GBK', 'UTF-8', zip_entry_name($entry));
if (!$size) { // 目錄
if (!is_dir($name)) mkdir($name, 0755, true);
continue;
}
if (!zip_entry_open($zip, $entry)) continue;
$content = zip_entry_read($entry, $size);
file_put_contents($name, $content);
echo "$size\t$name\n";
zip_entry_close($entry);
}
zip_close($zip);
?>
function extractZip($zipPath, $dest = '.', $fromEncoding = 'GBK', $toEncoding = 'UTF-8') {
$zip = new ZipArchive();
if ($zip->open($zipPath) !== true) throw new Exception("無法開啟 $zipPath");
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$rawName = $stat['name'];
$name = iconv($fromEncoding, $toEncoding . '//IGNORE', $rawName);
$target = $dest . DIRECTORY_SEPARATOR . $name;
if (substr($rawName, -1) === '/') { // 目錄
if (!is_dir($target)) mkdir($target, 0755, true);
continue;
}
// 確保父目錄存在
$dir = dirname($target);
if (!is_dir($dir)) mkdir($dir, 0755, true);
$content = $zip->getFromIndex($i);
file_put_contents($target, $content);
}
$zip->close();
}
// 使用
extractZip('other.zip', './extracted');
| 來源環境 | 常見編碼 | iconv 參數 |
|---|---|---|
| Windows 中文版 | GBK / CP936 | `iconv('GBK', 'UTF-8', ...)` |
| Linux/macOS | UTF-8 | 無需轉換 |
| 舊版日文 Windows | Shift_JIS | `iconv('SJIS', 'UTF-8', ...)` |
| 舊版繁中 Windows | Big5 | `iconv('Big5', 'UTF-8', ...)` |
若 ZIP 來源未知,可嘗試 `mb_detect_encoding($rawName, ['GBK','UTF-8','BIG5','SJIS'])` 自動偵測編碼。