在处理压缩文件时,PHP 提供了强大的 Zip 扩展来支持对 .zip 文件的读取与操作。本文将深入讲解 zip_read() 函数的用法,并配合其他相关函数,演示如何遍历 Zip 文件中的每一个条目并提取其中的内容或信息。
在使用 zip_read() 前,需确保你的 PHP 环境已启用 Zip 扩展。如果不确定,可使用如下代码查看扩展是否已加载:
<?php
if (class_exists('ZipArchive')) {
echo "Zip 扩展已启用";
} else {
echo "Zip 扩展未启用";
}
?>
如果返回结果是“Zip 扩展未启用”,你需要在 php.ini 文件中启用相关扩展,或在安装 PHP 时加入 --with-zip 选项。
zip_read() 是配合 zip_open() 和 zip_entry_* 系列函数使用的。它的作用是读取打开的 .zip 文件中的一个条目。每次调用会返回一个下一个条目的资源句柄,直到返回 false 表示没有更多的条目可读。
下面是一个完整的示例,展示如何打开一个 .zip 文件,遍历其所有条目,并读取每个条目的名称与内容:
<?php
$zipFile = '/path/to/example.zip'; // 替换为你本地的 zip 文件路径
$zip = zip_open($zipFile);
if (is_resource($zip)) {
while ($zip_entry = zip_read($zip)) {
echo "<strong>文件名:</strong> " . zip_entry_name($zip_entry) . "<br>";
if (zip_entry_open($zip, $zip_entry, "r")) {
$contents = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
echo "<strong>内容预览:</strong><br><pre>" . htmlentities(substr($contents, 0, 500)) . "</pre><hr>";
zip_entry_close($zip_entry);
}
}
zip_close($zip);
} else {
echo "无法打开压缩文件。";
}
?>
以下是与 zip_read() 搭配使用的关键函数:
zip_open(string $filename):打开 Zip 文件并返回资源句柄。
zip_read(resource $zip):从 Zip 文件资源中读取下一个条目。
zip_entry_name(resource $entry):获取当前条目的文件名。
zip_entry_open(resource $zip, resource $entry, string $mode):打开一个条目,准备读取内容。
zip_entry_read(resource $entry, int $length):读取当前打开条目的内容。
zip_entry_close(resource $entry):关闭打开的条目。
zip_close(resource $zip):关闭 Zip 文件资源。
当你构建一个用户可以上传 .zip 文件的系统时,可能需要对上传的文件内容进行扫描,比如过滤非法文件名、黑名单扩展名等。使用 zip_read() 可以实现逐项遍历并筛查的功能。
例如:
<?php
function scanZipForPhp($zipPath) {
$zip = zip_open($zipPath);
if (!is_resource($zip)) {
return false;
}
$suspicious = [];
while ($entry = zip_read($zip)) {
$name = zip_entry_name($entry);
if (preg_match('/\.php$/i', $name)) {
$suspicious[] = $name;
}
}
zip_close($zip);
return $suspicious;
}
$flaggedFiles = scanZipForPhp('/tmp/uploaded.zip');
if (!empty($flaggedFiles)) {
echo "发现可疑 PHP 文件:<br>";
echo implode('<br>', $flaggedFiles);
} else {
echo "未发现可疑文件。";
}
?>
zip_read() 和 zip_entry_* 系列函数是 PHP 较早期提供的方法,适用于较为底层的 Zip 操作。如果你需要更丰富的功能(如创建 Zip 文件、添加注释等),推荐使用 ZipArchive 类。
使用 zip_read() 无法直接访问加密压缩包中的内容。
若 Zip 文件内容较大,应避免一次性读取所有内容,防止内存溢出。