Skip to content

Zip 扩展

PHP 的 Zip 扩展提供了创建、读取和修改 ZIP 压缩文件的完整支持。ZIP 是最常见的归档格式之一,广泛用于文件打包、代码分发和数据备份。本节将全面讲解 PHP Zip 扩展的使用方法。

前置知识

阅读本节前,建议先了解:文件系统操作目录操作

基础概念

安装

bash
# 编译安装
./configure --enable-zip

# Ubuntu/Debian
sudo apt-get install php-zip

创建 ZIP 文件

基本创建

php
<?php
declare(strict_types=1);

$zip = new ZipArchive();
$filename = '/tmp/archive.zip';

if ($zip->open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
    throw new RuntimeException("无法创建 ZIP 文件");
}

// 添加文件
$zip->addFile('/path/to/file.txt', 'file.txt');
$zip->addFile('/path/to/image.jpg', 'images/photo.jpg');

// 添加空目录
$zip->addEmptyDir('docs/');

// 从字符串添加文件
$zip->addFromString('config.json', json_encode(['debug' => true], JSON_PRETTY_PRINT));

// 关闭(保存)
$zip->close();
echo "ZIP 文件创建成功: {$filename}" . PHP_EOL;

递归添加目录

php
<?php
declare(strict_types=1);

function zipDirectory(string $dir, string $archivePath): void
{
    $zip = new ZipArchive();
    if ($zip->open($archivePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        throw new RuntimeException("无法创建 ZIP: {$archivePath}");
    }

    $dir = rtrim($dir, DIRECTORY_SEPARATOR);

    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($iterator as $item) {
        $relativePath = substr($item->getPathname(), strlen($dir) + 1);

        if ($item->isDir()) {
            $zip->addEmptyDir($relativePath . '/');
        } else {
            $zip->addFile($item->getPathname(), $relativePath);
        }
    }

    $zip->close();
}

zipDirectory('/path/to/project', '/tmp/project.zip');

读取 ZIP 文件

php
<?php
declare(strict_types=1);

$zip = new ZipArchive();
if ($zip->open('/tmp/archive.zip') !== true) {
    throw new RuntimeException("无法打开 ZIP 文件");
}

// 获取文件数量和注释
echo "文件数: " . $zip->numFiles . PHP_EOL;
echo "注释: " . $zip->comment . PHP_EOL;
echo "状态: " . $zip->status . PHP_EOL;

// 遍历所有条目
for ($i = 0; $i < $zip->numFiles; $i++) {
    $stat = $zip->statIndex($i);
    echo "  {$stat['name']} - {$stat['size']} bytes - " . date('Y-m-d', $stat['mtime']) . PHP_EOL;
}

// 获取特定文件内容
$content = $zip->getFromName('file.txt');
echo $content;

// 提取单个文件
$zip->extractTo('/tmp/extracted', ['file.txt', 'config.json']);

// 提取所有文件
$zip->extractTo('/tmp/extracted_all');

// 检查文件是否存在
echo "file.txt 存在: " . ($zip->locateName('file.txt') !== false ? 'yes' : 'no') . PHP_EOL;

$zip->close();

修改 ZIP 文件

php
<?php
declare(strict_types=1);

$zip = new ZipArchive();
if ($zip->open('/tmp/archive.zip') !== true) {
    throw new RuntimeException("无法打开 ZIP 文件");
}

// 删除文件
$zip->deleteName('old-file.txt');
$zip->deleteIndex(2);

// 重命名文件
$zip->renameName('file.txt', 'renamed.txt');

// 设置注释
$zip->setArchiveComment('这是一个归档文件');

// 设置文件注释
$zip->setCommentName('file.txt', '重要配置文件');

$zip->close();

注意事项

  • 使用 ZipArchive::CREATE | ZipArchive::OVERWRITE 确保创建新文件
  • 大文件添加时注意内存使用
  • 提取时检查文件路径避免目录遍历攻击

下一节

继续学习:Zlib / Bzip2

参考链接