早期 PHP 常需引入第三方類別(如舊文中的 PHPZip)產生 ZIP。自 PHP 5.2 起,內建 ZipArchive 類別功能完整、效能優異,已成標準選擇。
<?php
function createAndDownloadZip(string $sourceDir, string $zipName): void
{
if (!is_dir($sourceDir)) {
throw new InvalidArgumentException("來源目錄不存在: $sourceDir");
}
$zip = new ZipArchive();
$tempFile = sys_get_temp_dir() . '/' . $zipName;
if ($zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new RuntimeException("無法建立暫存 ZIP 檔案");
}
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
$relativePath = substr($file->getPathname(), strlen($sourceDir) + 1);
if ($file->isDir()) {
$zip->addEmptyDir($relativePath);
} else {
$zip->addFile($file->getPathname(), $relativePath);
}
}
$zip->close();
// 輸出下載
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zipName . '"');
header('Content-Length: ' . filesize($tempFile));
readfile($tempFile);
unlink($tempFile); // 清理暫存檔
exit;
}
// 使用範例
createAndDownloadZip('/var/www/uploads/user_123', 'backup_' . date('Ymd') . '.zip');
?>
<?php
$zip = new ZipArchive();
$zip->open('secure.zip', ZipArchive::CREATE);
// 設定密碼(PHP 7.2+,需 libzip 1.2+)
$zip->setPassword('strong_password');
$zip->setEncryptionName('secret.txt', ZipArchive::EM_AES_256);
$zip->addFromString('secret.txt', '機密內容');
$zip->setArchiveComment('加密備份 ' . date('Y-m-d H:i:s'));
$zip->close();
?>
addFile 過大檔案導致記憶體飆升;ZipArchive 以串流方式寫入,通常不佔用大量記憶體。ZipArchive::CREATE 搭配 ZipArchive::OVERWRITE 分卷或改用 tar.gz。| 錯誤 | 原因 | 解決 |
|---|---|---|
| Class 'ZipArchive' not found | 未安裝 php-zip 擴充 | apt-get install php-zip 或 yum install php-pecl-zip |
| Permission denied | 目錄權限不足 | 確認 PHP 執行身份對來源目錄有讀取權限 |
| Maximum execution time exceeded | 壓縮耗時過長 | 調大 set_time_limit(0) 或改非同步處理 |