首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP ZipArchive 完整操作指南:建立、讀取、新增、刪除、解壓縮與加密

     編輯:PHP 相關知識

ZipArchive 是 PHP 內建處理 ZIP 檔案的類別,支援建立新壓縮檔、讀取現有檔案、列出內容、解壓縮、新增/刪除/重命名檔案、設定註解、甚至加密(PHP 7.2+)。本文提供完整操作手冊,涵蓋所有常見場景與錯誤處理最佳實踐。

核心常數:開啟模式

常數說明
ZipArchive::CREATE建立新檔,若存在則覆蓋
ZipArchive::OVERWRITE覆蓋現有檔(等同 CREATE)
ZipArchive::EXCL獨佔建立,檔案存在則失敗
ZipArchive::CHECKCONS檢查一致性,失敗則不開啟
ZipArchive::RDONLY唯讀模式開啟

1. 建立新 ZIP 並新增檔案/目錄

<?php
$zip = new ZipArchive();
$filename = 'backup_' . date('Ymd_His') . '.zip';

if ($zip->open($filename, ZipArchive::CREATE) !== true) {
    die("無法建立 ZIP: $filename");
}

// 新增單一檔案(第二參數為 ZIP 內路徑)
$zip->addFile('/var/www/html/index.php', 'public/index.php');
$zip->addFile('/var/www/html/.env', 'config/.env'); // 重新命名路徑

// 新增字串內容為檔案
$zip->addFromString('README.txt', "專案備份\n建立時間: " . date('c'));

// 遞歸新增整個目錄
function addDirRecursive(ZipArchive $zip, string $realPath, string $zipPath): void
{
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($realPath, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($iterator as $item) {
        $relativePath = $zipPath . '/' . $iterator->getSubPathName();
        if ($item->isDir()) {
            $zip->addEmptyDir($relativePath);
        } else {
            $zip->addFile($item->getPathname(), $relativePath);
        }
    }
}

addDirRecursive($zip, '/var/www/html/storage', 'storage');

$zip->close();
echo "ZIP 建立完成: $filename";
?>

2. 讀取 ZIP 內容列表

<?php
$zip = new ZipArchive();
if ($zip->open('backup.zip') !== true) die("開啟失敗");

echo "檔案總數: {$zip->count()}\n";
echo "狀態: {$zip->status}\n";
echo "註解: " . ($zip->getComment() ?: '(無)') . "\n";

for ($i = 0; $i < $zip->count(); $i++) {
    $stat = $zip->statIndex($i);
    echo sprintf(
        "[%d] %-50s %10d bytes  壓縮後: %10d  CRC32: %08X  時間: %s\n",
        $i,
        $stat['name'],
        $stat['size'],
        $stat['comp_size'],
        $stat['crc'],
        date('Y-m-d H:i:s', $stat['mtime'])
    );
}
$zip->close();
?>

3. 解壓縮(提取)檔案

<?php
$zip = new ZipArchive();
if ($zip->open('backup.zip') !== true) die("開啟失敗");

// 提取全部到目錄
$zip->extractTo('/restore/path');

// 或提取特定檔案
$zip->extractTo('/restore/path', ['public/index.php', 'config/.env']);

// 提取單一檔案到字串(不寫入磁碟)
$content = $zip->getFromName('README.txt');
if ($content !== false) {
    echo "README 內容:\n$content";
}

$zip->close();
?>

4. 刪除 ZIP 內檔案/目錄

<?php
$zip = new ZipArchive();
// 必須用 OVERWRITE 或 CREATE 模式開啟才能修改
if ($zip->open('backup.zip', ZipArchive::OVERWRITE) !== true) die("開啟失敗");

// 刪除單一檔案
$zip->deleteName('config/.env');

// 刪除目錄(需先刪除裡面所有檔案,或遞歸刪除)
// ZipArchive 無直接刪除目錄方法,需遍歷刪除
$prefix = 'storage/';
for ($i = $zip->count() - 1; $i >= 0; $i--) {
    $name = $zip->getNameIndex($i);
    if (str_starts_with($name, $prefix)) {
        $zip->deleteIndex($i);
    }
}

$zip->close();
echo "刪除完成";
?>

5. 更新/重命名 ZIP 內檔案

<?php
$zip = new ZipArchive();
if ($zip->open('backup.zip', ZipArchive::OVERWRITE) !== true) die("開啟失敗");

// 重命名:讀取內容 → 新增新名稱 → 刪除舊名稱
$oldName = 'public/index.php';
$newName = 'public/index_v2.php';

$content = $zip->getFromName($oldName);
if ($content !== false) {
    $zip->addFromString($newName, $content);
    $zip->deleteName($oldName);
    echo "重命名完成: $oldName -> $newName";
}

// 更新檔案內容
$zip->addFromString('README.txt', "更新後的說明\n" . date('c'));

$zip->close();
?>

6. ZIP 加密與密碼保護(PHP 7.2+ / libzip 1.2+)

<?php
$zip = new ZipArchive();
if ($zip->open('secret.zip', ZipArchive::CREATE) !== true) die("建立失敗");

$zip->addFromString('secret.txt', '這是機密資料');

// 設定加密密碼(支援 AES-256,需 libzip 1.6+)
$zip->setPassword('StrongP@ssw0rd!');
$zip->setEncryptionName('secret.txt', ZipArchive::EM_AES_256);

$zip->close();

// 解壓縮時需提供密碼
$zip2 = new ZipArchive();
if ($zip2->open('secret.zip') === true) {
    $zip2->setPassword('StrongP@ssw0rd!');
    $zip2->extractTo('/decrypted');
    $zip2->close();
}
?>

7. 進階:記憶體中建立 ZIP(不落地,直接下載)

<?php
$zip = new ZipArchive();
// 開啟虛擬記憶體檔案(PHP 8.0+ 支援 "php://memory")
if ($zip->open('php://memory', ZipArchive::CREATE) !== true) die("失敗");

$zip->addFromString('data.json', json_encode(['users' => 123, 'time' => time()]));
$zip->addFromString('log.txt', "系統日誌...\n");

$zip->close();

// 取得二進位內容
$zipData = file_get_contents('php://memory'); // 注意:close 後可能無法讀取
// 正確做法:open 時用 variable:// 參考(PHP 8.2+)
// 或改用 tempnam() 暫存檔

// 直接輸出下載
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="export.zip"');
echo $zipData;
?>

常見錯誤與解決方案

錯誤原因與解決
open() 回傳整數錯誤碼非 true 即失敗。常見碼:9=找不到檔, 10=非 ZIP, 11=記憶體不足, 14=權限不足。用 ZipArchive::getStatusString() (PHP 8.0+) 取得訊息。
中文檔名亂碼ZIP 標準早期不支援 UTF-8。確保 PHP 7.2+、libzip 1.6+,檔名會自動用 UTF-8 標記。舊系統解壓需指定編碼(如 `unzip -O cp950`)。
大檔案記憶體耗盡避免 getFromName() 讀取巨大檔案到記憶體。改用 extractTo() 直接寫入磁碟。
無法刪除目錄ZipArchive 無遞歸刪除目錄 API,必須先刪除所有子檔案(由後往前遍歷索引)。
加密不支援需 PHP 7.2+ 且編譯時啟用 --with-libzip(系統 libzip ≥ 1.2)。共享主機常不支援,請確認 phpinfo() 的 zip 區塊。

效能優化建議

  • 大量檔案壓縮:關閉壓縮 $zip->setCompressionName($name, ZipArchive::CM_STORE) 加速,或平行處理(多進程各壓縮部分再合併)。
  • 串流處理:搭配 ZipStream 套件(composer require maennchen/zipstream-php)實現「邊產生邊下載」,零記憶體佔用。
  • 重複操作:同一 ZIP 多次修改,保持開啟狀態批次處理,最後統一 close()。

ZipArchive 功能強大且無外部相依,是 PHP 專案處理封裝、備份、匯出、下載的首選工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved