本文目录导读:

在PHP中操作ZIP文件,主要使用内置的 ZipArchive 类,以下是全面的操作指南:
环境检查
// 检查ZIP扩展是否可用
if (!extension_loaded('zip')) {
echo "ZIP扩展未启用";
exit;
}
// 查看ZipArchive版本
echo ZipArchive::LIBZIP_VERSION; // 输出libzip版本
基础操作
创建ZIP文件
$zip = new ZipArchive();
$zipPath = 'my_archive.zip';
if ($zip->open($zipPath, ZipArchive::CREATE) === TRUE) {
// 添加文件
$zip->addFile('file.txt', 'file.txt'); // 添加现有文件
$zip->addFile('path/to/file.jpg', 'images/photo.jpg'); // 添加并重命名
// 添加空目录
$zip->addEmptyDir('empty_folder');
// 直接添加字符串内容(不创建物理文件)
$zip->addFromString('readme.txt', "Hello world");
// 关闭ZIP
$zip->close();
echo "ZIP文件创建成功";
} else {
echo "无法创建ZIP文件";
}
解压ZIP文件
$zip = new ZipArchive();
if ($zip->open('my_archive.zip') === TRUE) {
// 解压到目录
$zip->extractTo('/destination/path/');
// 只解压特定文件
$zip->extractTo('/destination/path/', ['file.txt', 'images/photo.jpg']);
$zip->close();
echo "解压成功";
} else {
echo "无法打开ZIP文件";
}
高级操作
遍历ZIP内容
$zip = new ZipArchive();
if ($zip->open('my_archive.zip') === TRUE) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$fileInfo = $zip->statIndex($i);
echo "文件名: " . $fileInfo['name'] . "<br>";
echo "大小: " . $fileInfo['size'] . " bytes<br>";
echo "压缩方式: " . $fileInfo['comp_method'] . "<br>";
echo "压缩后大小: " . $fileInfo['comp_size'] . " bytes<br>";
echo "时间戳: " . date('Y-m-d H:i:s', $fileInfo['mtime']) . "<br>";
echo "---<br>";
}
$zip->close();
}
$zip = new ZipArchive();
if ($zip->open('my_archive.zip') === TRUE) {
// 获取文件内容
$content = $zip->getFromName('readme.txt');
// 通过索引获取内容
$content2 = $zip->getFromIndex(0);
// 流式读取大文件(节省内存)
$fp = $zip->getStream('large_file.bin');
if ($fp) {
while (!feof($fp)) {
$chunk = fread($fp, 8192); // 8KB chunks
// 处理数据
}
fclose($fp);
}
$zip->close();
}
删除和重命名
$zip = new ZipArchive();
if ($zip->open('my_archive.zip') === TRUE) {
// 删除文件
$zip->deleteName('file.txt');
// 通过索引删除
$zip->deleteIndex(0);
// 重命名文件
$zip->renameName('old.txt', 'new.txt');
// 重命名目录
$zip->renameName('old_folder', 'new_folder');
$zip->close();
}
实用工具函数
完整目录压缩
function zipDirectory($sourceDir, $zipFile) {
// 递归删除前先检查目录
if (!is_dir($sourceDir)) {
return false;
}
$zip = new ZipArchive();
if ($zip->open($zipFile, ZipArchive::CREATE) !== TRUE) {
return false;
}
// 递归添加目录的方法
$dir = rtrim($sourceDir, '/');
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
$filePath = $file->getPathname();
$relativePath = substr($filePath, strlen($dir) + 1);
if ($file->isDir()) {
$zip->addEmptyDir($relativePath);
} else {
$zip->addFile($filePath, $relativePath);
}
}
return $zip->close();
}
// 使用
zipDirectory('/path/to/source', '/path/to/output.zip');
带进度显示的解压
function extractWithProgress($zipFile, $destination) {
$zip = new ZipArchive();
if ($zip->open($zipFile) !== TRUE) {
return false;
}
$totalFiles = $zip->numFiles;
$processed = 0;
for ($i = 0; $i < $totalFiles; $i++) {
// 提取单个文件(保持目录结构)
$zip->extractTo($destination, [$zip->getNameIndex($i)]);
$processed++;
$progress = ($processed / $totalFiles) * 100;
echo sprintf("进度: %.1f%%\n", $progress);
flush();
}
$zip->close();
return true;
}
错误处理
try {
$zip = new ZipArchive();
// 使用异常处理
if (@$zip->open('file.zip') !== TRUE) {
throw new Exception('无法打开ZIP文件');
}
if (!$zip->addFile('non_existent.txt')) {
throw new Exception('文件添加失败');
}
// 其他操作...
if (!$zip->close()) {
throw new Exception('ZIP关闭失败');
}
} catch (Exception $e) {
error_log('ZIP操作错误: ' . $e->getMessage());
if (isset($zip)) {
$zip->close(); // 确保关闭
}
}
流式上传处理
// 处理上传的ZIP文件
if ($_FILES['zipfile']['error'] === UPLOAD_ERR_OK) {
$tmpFile = $_FILES['zipfile']['tmp_name'];
$zip = new ZipArchive();
if ($zip->open($tmpFile) === TRUE) {
// 安全解压(防止路径遍历攻击)
$extractPath = '/safe/directory/';
array_map(function($entry) use ($extractPath) {
// 安全检查:防止 '../' 等路径
if (strpos($entry, '..') !== false || strpos($entry, '/') === 0) {
throw new Exception('不安全的文件路径');
}
}, array_column(range(0, $zip->numFiles - 1), 0));
$zip->extractTo($extractPath);
$zip->close();
}
}
压缩方式设置
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
// 设置压缩级别
$zip->setCompressionName('file.txt', ZipArchive::CM_DEFLATE, 9); // 最高压缩
// 对整个压缩包设置压缩
$zip->setArchiveComment('This is an archive comment');
$zip->setCompressionIndex(0, ZipArchive::CM_STORE); // 无压缩
// 添加加密文件(libzip >= 1.2.0)
$zip->setPassword('secret_password');
$zip->addFile('file.txt', 'encrypted.txt');
$zip->close();
这些操作覆盖了PHP处理ZIP文件的主要场景,在生产环境中,还需要注意:
- 内存限制和上传大小限制
- 文件权限和安全性检查
- 大文件的流式处理
- 编码问题(UTF-8文件名)