| 方法 | 說明 |
open($filename, $flags) | 開啟壓縮檔,ZipArchive::CREATE、OVERWRITE、EXCL、CHECKCONS |
close() | 關閉並寫入磁碟 |
addFile($path, $localname) | 加入檔案 |
addFromString($name, $content) | 從字串加入 |
addGlob($pattern, $flags, $options) | 依模式批量加入 |
addPattern($pattern, $path, $options) | 依正則批量加入 |
extractTo($destination, $entries) | 解壓縮到目錄 |
getFromName($name) | 讀取項目內容 (字串) |
getFromIndex($index) | 按索引讀取內容 |
getStream($name) | 取得資源串流 (大檔案) |
deleteName($name) | 刪除項目 |
renameName($old, $new) | 重新命名 |
setPassword($password) | 設定解密密碼 (PHP 7.2+) |
setEncryptionName($name, $method, $password) | 設定項目加密 (PHP 7.2+) |
count() | 項目數量 |
statName($name) | 取得項目資訊 (大小、壓縮大小、CRC、時間、壓縮方法) |
locateName($name) | 查找項目索引 |
getNameIndex($index) | 索引轉名稱 |
setCommentName($name, $comment) | 設定項目註解 |
getCommentName($name) | 取得項目註解 |
setArchiveComment($comment) | 設定壓縮檔註解 |
getArchiveComment() | 取得壓縮檔註解 |
實戰範例集
1. 建立壓縮檔 (資料夾打包)
function createZipFromDir($sourceDir, $outputZip) {
$zip = new ZipArchive();
if ($zip->open($outputZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new Exception("無法建立壓縮檔: $outputZip");
}
$sourceDir = rtrim($sourceDir, '/\\');
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($files as $file) {
$filePath = $file->getPathname();
$relativePath = substr($filePath, strlen($sourceDir) + 1);
if ($file->isDir()) {
$zip->addEmptyDir($relativePath);
} else {
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
return true;
}
// 使用
createZipFromDir('/path/to/source', '/path/to/archive.zip');
2. 解壓縮到指定目錄
function extractZip($zipPath, $destDir) {
$zip = new ZipArchive();
$res = $zip->open($zipPath);
if ($res !== true) {
throw new Exception("無法開啟壓縮檔: $zipPath (錯誤碼: $res)");
}
// 可選:只解壓特定項目
// $zip->extractTo($destDir, ['file1.txt', 'folder/']);
$zip->extractTo($destDir);
$zip->close();
return true;
}
3. 讀取壓縮檔內容不解壓 (記憶體高效)
function readZipEntry($zipPath, $entryName) {
$zip = new ZipArchive();
if ($zip->open($zipPath) !== true) return false;
// 方法 1: 完整讀入記憶體 (小檔案)
$content = $zip->getFromName($entryName);
// 方法 2: 串流讀取 (大檔案)
// $stream = $zip->getStream($entryName);
// $content = stream_get_contents($stream);
// fclose($stream);
$zip->close();
return $content;
}
4. 列出壓縮檔所有項目資訊
function listZipContents($zipPath) {
$zip = new ZipArchive();
if ($zip->open($zipPath) !== true) return [];
$list = [];
for ($i = 0; $i < $zip->count(); $i++) {
$stat = $zip->statIndex($i);
$list[] = [
'name' => $stat['name'],
'size' => $stat['size'],
'comp_size' => $stat['comp_size'],
'crc32' => sprintf('%08X', $stat['crc']),
'mtime' => date('Y-m-d H:i:s', $stat['mtime']),
'method' => $stat['comp_method'], // 0=store, 8=deflate, 12=bzip2, 14=lzma, 98=zstd
'is_dir' => substr($stat['name'], -1) === '/'
];
}
$zip->close();
return $list;
}
5. 加密壓縮檔 (PHP 7.2+)
function createEncryptedZip($files, $outputZip, $password) {
$zip = new ZipArchive();
if ($zip->open($outputZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new Exception("建立失敗");
}
$zip->setPassword($password);
foreach ($files as $name => $content) {
$zip->addFromString($name, $content);
$zip->setEncryptionName($name, ZipArchive::EM_AES_256, $password);
}
$zip->close();
return true;
}
6. 記憶體建立壓縮檔並直接輸出下載 (不落地)
function streamZipDownload($files, $filename = 'download.zip') {
// 需啟用 zlib.output_compression = Off
$tempZip = 'php://temp';
$zip = new ZipArchive();
if ($zip->open($tempZip, ZipArchive::CREATE) !== true) {
throw new Exception("記憶體建立失敗");
}
foreach ($files as $name => $content) {
$zip->addFromString($name, $content);
}
$zip->close();
// 重新開啟讀取
$zip->open($tempZip);
header('Content-Type: application/zip');
header("Content-Disposition: attachment; filename=\"$filename\"");
header('Content-Length: ' . $zip->statIndex(0)['size']); // 近似值
echo $zip->getFromIndex(0); // 實際需迴圈輸出所有項目,或使用串流
$zip->close();
}
傳統函數式 API (舊代碼維護)
| 函數 | 說明 |
zip_open($path) | 開啟壓縮檔,回傳資源 |
zip_read($zip) | 讀取下一個項目 |
zip_entry_open($zip, $entry, $mode) | 開啟項目讀取 |
zip_entry_read($entry, $length) | 讀取項目內容 |
zip_entry_close($entry) | 關閉項目 |
zip_close($zip) | 關閉壓縮檔 |
zip_entry_name($entry) | 取得項目名稱 |
zip_entry_filesize($entry) | 原始大小 |
zip_entry_compressedsize($entry) | 壓縮大小 |
zip_entry_compressionmethod($entry) | 壓縮方法 |
常見問題與限制
| 問題 | 說明/對策 |
| 大檔案記憶體耗盡 | 使用 getStream() 串流處理,避免 getFromName() 全讀入記憶體 |
| 中文檔名亂碼 | PHP 8.0+ 支援 UTF-8 檔名;舊版需手動轉碼或使用 zip_entry_name 讀取原始位元組 |
| 壓縮等級控制 | ZipArchive 無直接設定,需編譯時指定 --with-libzip 並使用 setCompressionIndex() (PHP 8.0+) |
| 4GB+ 壓縮檔 | 需 Zip64 支援 (libzip 1.6+,PHP 7.3+),開啟時加 ZipArchive::CREATE | ZipArchive::OVERWRITE |
| 加密相容性 | AES-256 需解壓工具支援 (7-Zip, WinRAR, macOS Finder 皆支援) |
| 權限保留 | ZipArchive 不保留 Unix 權限,需自行記錄恢復 |
總結
PHP Zip 擴展透過 ZipArchive 提供功能完整、記憶體安全的壓縮檔操作介面。掌握建立、讀取、解壓縮、加密、串流處理等核心模式,即可滿足檔案打包下載、上傳解壓、資料備份、文件交換等多數業務需求。大檔案、高併發場景建議結合串流 API 與非同步處理佇列。
- 上一篇文章: PHP 時區完整列表:支援的時區識別符與最佳實務設定指南
- 下一篇文章: PHP XML 解析器完全指南:Expat 事件驅動解析、核心函數與實戰模式
Copyright ©
程式碼之家 All Rights Reserved