PHP操作ZIP核心是ZipArchive类,用于创建、读取、解压ZIP文件。通过addFile添加文件,extractTo解压,getNameIndex遍历文件列表。处理大文件需注意内存和执行时间限制,建议分批处理或异步执行。解压时面临编码问题,可尝试iconv转换文件名编码;安全风险如路径遍历需通过isSafeFileName校验文件名,限制解压目录。替代方案包括zlib扩展处理.gz文件,PharData类支持.tar.gz等格式,或调用系统命令但需防范注入风险。

PHP操作ZIP压缩包的核心是利用PHP内置的
ZipArchive
ZipArchive
要使用PHP操作ZIP压缩包,主要涉及以下几个核心步骤和代码示例:
1. 创建并添加文件到ZIP压缩包
这通常用于将应用程序生成的文件、用户上传的图片集合等打包。
立即学习“PHP免费学习笔记(深入)”;
<?php
$zipFileName = 'my_archive.zip';
$zip = new ZipArchive();
// ZIPARCHIVE::CREATE 表示如果文件不存在则创建
// ZIPARCHIVE::OVERWRITE 表示如果文件存在则覆盖
if ($zip->open($zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
// 添加一个文件,路径是文件在服务器上的实际路径
$filePath1 = '/path/to/your/file1.txt';
if (file_exists($filePath1)) {
$zip->addFile($filePath1, 'file1.txt'); // 第二个参数是文件在压缩包中的名称
} else {
echo "文件 {$filePath1} 不存在,无法添加到压缩包。
";
}
// 添加另一个文件,并指定在压缩包中的子目录
$filePath2 = '/path/to/another/image.jpg';
if (file_exists($filePath2)) {
$zip->addFile($filePath2, 'images/image.jpg');
} else {
echo "文件 {$filePath2} 不存在,无法添加到压缩包。
";
}
// 添加一个字符串作为文件内容(不需要实际文件)
$zip->addFromString('readme.txt', '这是一个通过PHP创建的ZIP文件。');
// 添加一个空目录
$zip->addEmptyDir('empty_folder');
// 完成操作并关闭压缩包
$zip->close();
echo "ZIP文件 {$zipFileName} 创建成功。
";
} else {
echo "无法创建ZIP文件。
";
}
?>2. 解压ZIP压缩包
这在处理用户上传的包含多个文件的ZIP包时非常有用。
<?php
$zipFileName = 'my_archive.zip';
$extractPath = 'extracted_files/'; // 解压到这个目录
$zip = new ZipArchive();
if ($zip->open($zipFileName) === TRUE) {
// 确保解压目录存在,如果不存在则创建
if (!is_dir($extractPath)) {
mkdir($extractPath, 0777, true);
}
// 将所有文件解压到指定目录
// extractTo() 返回 true 表示成功,false 表示失败
if ($zip->extractTo($extractPath)) {
echo "ZIP文件 {$zipFileName} 成功解压到 {$extractPath}
";
} else {
echo "解压ZIP文件失败。
";
}
$zip->close();
} else {
echo "无法打开ZIP文件 {$zipFileName}。
";
}
?>3. 列出ZIP压缩包中的文件
有时候我们只想查看ZIP包里有什么,而不是全部解压。
<?php
$zipFileName = 'my_archive.zip';
$zip = new ZipArchive();
if ($zip->open($zipFileName) === TRUE) {
echo "ZIP文件 {$zipFileName} 包含以下文件:
";
for ($i = 0; $i < $zip->numFiles; $i++) {
$fileName = $zip->getNameIndex($i);
echo "- " . $fileName . "
";
}
$zip->close();
} else {
echo "无法打开ZIP文件 {$zipFileName}。
";
}
?>在我个人经验里,处理大文件或包含大量小文件的复杂目录结构时,
ZipArchive
memory_limit
addFromString
addFile
其次,执行时间(
max_execution_time
exec
zip
unzip
最佳实践:
addGlob
open()
addFile()
extractTo()
ZipArchive
addFile
解压ZIP文件时,编码问题和安全风险是两个非常实际的“坑”。我曾经遇到过从Windows系统打包的ZIP文件在Linux服务器上解压后文件名乱码的情况,那真是让人头疼。这通常是由于ZIP文件内部存储的文件名编码与服务器默认编码不一致造成的。
编码问题: ZIP文件格式本身对文件名编码没有强制规定,导致不同操作系统或压缩工具可能使用不同的编码(如GBK、UTF-8、Shift-JIS等)。
ZipArchive
ZipArchive
iconv()
mb_convert_encoding()
ZipArchive
getNameIndex()
安全风险: 解压用户上传的ZIP文件时,最大的安全风险是路径遍历(Path Traversal)。恶意用户可能会在ZIP包中包含像
../../etc/passwd
解决方案:
严格的解压目录限制: 始终将文件解压到专门的、独立的、且Web服务器无执行权限的目录中。
文件名清理与验证: 在解压前,遍历ZIP包中的所有文件名(
getNameIndex()
..
/
:
// 示例:检查文件名是否安全
function isSafeFileName($fileName) {
// 拒绝包含路径遍历符
if (strpos($fileName, '../') !== false || strpos($fileName, '..\') !== false) {
return false;
}
// 拒绝绝对路径(尽管ZipArchive通常会处理,但多一层检查更安全)
if (strpos($fileName, '/') === 0 || strpos($fileName, '\') === 0 || strpos($fileName, ':') !== false) {
return false;
}
// 拒绝包含控制字符或非打印字符
if (preg_match('/[[:cntrl:]]/', $fileName)) {
return false;
}
return true;
}
// 在 extractTo 之前遍历检查
// ... (打开ZipArchive)
for ($i = 0; $i < $zip->numFiles; $i++) {
$fileName = $zip->getNameIndex($i);
if (!isSafeFileName($fileName)) {
error_log("发现不安全的文件名:{$fileName},拒绝解压。");
$zip->close();
return false; // 或者跳过这个文件
}
}
// ... (执行 extractTo)白名单机制: 如果可能,只允许解压特定类型的文件(例如,只允许图片文件),拒绝其他所有文件。
权限控制: 解压目录的权限应该设置得尽可能严格,只允许PHP进程写入,并确保Web服务器不能直接执行其中的文件。
虽然
ZipArchive
.zip
.tar.gz
.gz
GZ压缩(zlib
.gz
zlib
gzcompress()
gzuncompress()
gzencode()
gzdecode()
gzopen()
gzread()
gzwrit()
gzclose()
.gz
// 示例:使用gzopen读取.gz文件
$gzFile = 'data.txt.gz';
if (file_exists($gzFile)) {
$handle = gzopen($gzFile, 'rb'); // 'rb' 表示以二进制读模式打开
if ($handle) {
while (!gzeof($handle)) {
echo gzread($handle, 4096); // 每次读取4KB
}
gzclose($handle);
}
}TAR归档(PharData
.tar
.tar.gz
.tar.bz2
PharData
Phar
PharData
Phar
// 示例:创建并添加文件到.tar.gz
$phar = new PharData('my_archive.tar');
$phar->addFile('/path/to/file1.txt', 'file1.txt');
$phar->addFile('/path/to/file2.txt', 'folder/file2.txt');
$phar->compress(Phar::GZ); // 压缩成.tar.gz
unlink('my_archive.tar'); // 原始.tar文件可以删除了
echo "创建了 my_archive.tar.gz
";
// 示例:解压.tar.gz
$pharData = new PharData('my_archive.tar.gz');
$pharData->extractTo('extracted_tar_files/');
echo "解压了 my_archive.tar.gz
";PharData
ZipArchive
addFile
extractTo
外部命令调用(exec
shell_exec
.rar
exec()
shell_exec()
zip
unzip
tar
gzip
rar
unrar
// 示例:使用系统unzip命令解压
$zipFile = 'another_archive.zip';
$targetDir = 'external_extracted/';
if (!is_dir($targetDir)) {
mkdir($targetDir, 0777, true);
}
$command = "unzip -o " . escapeshellarg($zipFile) . " -d " . escapeshellarg($targetDir);
$output = shell_exec($command);
echo "外部命令解压输出:
" . $output . "
";注意: 使用外部命令存在显著的安全风险,特别是当命令参数包含用户输入时。务必使用
escapeshellarg()
escapeshellcmd()
以上就是php如何操作zip压缩包_php压缩和解压文件方法的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号