zip_open

(PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.0.0)

zip_open打开一个 ZIP 文件存档

警告

此函数在 PHP 8.0.0 中已弃用。强烈建议不要依赖此函数。

描述

zip_open(string $filename): resource|int|false

打开一个新的 ZIP 存档以供读取。

参数

filename

要打开的 ZIP 存档的文件名。

返回值

返回一个资源句柄,供以后使用 zip_read()zip_close(),或者返回 false 或者错误数量(如果 filename 不存在或发生其他错误)。

变更日志

版本 描述
8.0.0 此函数已被弃用,建议使用对象 API,参见 ZipArchive::open()

参见

添加注释

用户贡献的注释 13 个注释

26
david at php dot net
15 年前
请注意,Zip 函数在发生错误时会返回一个整数错误号。因此

<?php
$zip
= zip_open($file);

if (
$zip) {
?>

是错误的。应该使用

<?php
$zip
= zip_open($file);

if (
is_resource($zip)) {
?>
5
saulius at solmetra dot lt
17 年前
一些旧版本的 PHP 在 zip_open 失败时会返回 false,而新版本则返回错误数量(作为整数),所以不要使用

$zip = zip_open($zip_file);
if ($zip) {
// 认为 ZIP 文件成功打开
}

而应该使用

$zip = zip_open($zip_file);
if (is_resource($zip)) {
// 认为 ZIP 文件成功打开
}

您也可以使用此函数通过错误号获取错误消息

function zipFileErrMsg($errno) {
// 使用常量名称作为字符串以使此函数与 PHP4 兼容
$zipFileFunctionsErrors = array(
'ZIPARCHIVE::ER_MULTIDISK' => '不支持多磁盘 ZIP 存档。',
'ZIPARCHIVE::ER_RENAME' => '重命名临时文件失败。',
'ZIPARCHIVE::ER_CLOSE' => '关闭 ZIP 存档失败',
'ZIPARCHIVE::ER_SEEK' => '查找错误',
'ZIPARCHIVE::ER_READ' => '读取错误',
'ZIPARCHIVE::ER_WRITE' => '写入错误',
'ZIPARCHIVE::ER_CRC' => 'CRC 错误',
'ZIPARCHIVE::ER_ZIPCLOSED' => '包含的 ZIP 存档已关闭',
'ZIPARCHIVE::ER_NOENT' => '没有此文件。',
'ZIPARCHIVE::ER_EXISTS' => '文件已存在',
'ZIPARCHIVE::ER_OPEN' => '无法打开文件',
'ZIPARCHIVE::ER_TMPOPEN' => '无法创建临时文件。',
'ZIPARCHIVE::ER_ZLIB' => 'Zlib 错误',
'ZIPARCHIVE::ER_MEMORY' => '内存分配失败',
'ZIPARCHIVE::ER_CHANGED' => '条目已更改',
'ZIPARCHIVE::ER_COMPNOTSUPP' => '不支持压缩方法。',
'ZIPARCHIVE::ER_EOF' => '过早的 EOF',
'ZIPARCHIVE::ER_INVAL' => '无效参数',
'ZIPARCHIVE::ER_NOZIP' => '不是 ZIP 存档',
'ZIPARCHIVE::ER_INTERNAL' => '内部错误',
'ZIPARCHIVE::ER_INCONS' => 'ZIP 存档不一致',
'ZIPARCHIVE::ER_REMOVE' => '无法删除文件',
'ZIPARCHIVE::ER_DELETED' => '条目已被删除',
);
$errmsg = 'unknown';
foreach ($zipFileFunctionsErrors as $constName => $errorMessage) {
if (defined($constName) and constant($constName) === $errno) {
return 'Zip File Function error: '.$errorMessage;
}
}
return 'Zip File Function error: unknown';
}

$zip = zip_open($zip_file);
if (!is_resource($zip)) {
die(zipFileErrMsg($zip));
}
5
fuljencio at gmail dot com
14 年前
获取 Mozilla 附加组件版本(例如 Firefox 扩展)

<?php
function get_addon_version($path)
{
// 打开 ZIP
$zip = zip_open($path);

// 查找条目
do {
$entry = zip_read($zip);
} while (
$entry && zip_entry_name($entry) != "install.rdf");

// 打开条目
zip_entry_open($zip, $entry, "r");

// 读取条目
$entry_content = zip_entry_read($entry, zip_entry_filesize($entry));

// <em:version> 的位置
$version_open_pos = strpos($entry_content, "<em:version>");

// </em:version> 的位置
$version_close_pos = strpos($entry_content, "</em:version>", $version_open_pos);

// 版本
$version = substr(
$entry_content,
$version_open_pos + strlen("<em:version>"),
$version_close_pos - ($version_open_pos + strlen("<em:version>"))
);

// 关闭条目
zip_entry_close($entry);

// 关闭 ZIP
zip_close($zip);

return
$version;
}
?>
1
bisqwit at iki dot fi
18 年前
如果您的 PHP 安装没有 zip_open 函数,而且您无论如何都无法安装它,那么如果服务器可以访问 "unzip" 实用程序(大多数 Linux 系统都有),您可以使用这些函数代替。
到目前为止,我只在 Fedora Core 3 中测试过这些。
使用风险自负。

<?php

function ShellFix($s)
{
return
"'".str_replace("'", "'\''", $s)."'";
}

function
zip_open($s)
{
$fp = @fopen($s, 'rb');
if(!
$fp) return false;

$lines = Array();
$cmd = 'unzip -v '.shellfix($s);
exec($cmd, $lines);

$contents = Array();
$ok=false;
foreach(
$lines as $line)
{
if(
$line[0]=='-') { $ok=!$ok; continue; }
if(!
$ok) continue;

$length = (int)$line;
$fn = trim(substr($line,58));

$contents[] = Array('name' => $fn, 'length' => $length);
}

return
Array(
'fp' => $fp,
'name' => $s,
'contents' => $contents,
'pointer' => -1);
}
function
zip_read(&$fp)
{
if(!
$fp) return false;

$next = $fp['pointer'] + 1;
if(
$next >= count($fp['contents'])) return false;

$fp['pointer'] = $next;
return
$fp['contents'][$next];
}
function
zip_entry_name(&$res)
{
if(!
$res) return false;
return
$res['name'];
}
function
zip_entry_filesize(&$res)
{
if(!
$res) return false;
return
$res['length'];
}
function
zip_entry_open(&$fp, &$res)
{
if(!
$res) return false;

$cmd = 'unzip -p '.shellfix($fp['name']).' '.shellfix($res['name']);

$res['fp'] = popen($cmd, 'r');
return !!
$res['fp'];
}
function
zip_entry_read(&$res, $nbytes)
{
return
fread($res['fp'], $nbytes);
}
function
zip_entry_close(&$res)
{
fclose($res['fp']);
unset(
$res['fp']);
}
function
zip_close(&$fp)
{
fclose($fp['fp']);
}
?>
1
匿名
15 年前
注意,此函数忽略自定义流包装器,例如通过 stream_wrapper_register 创建的包装器 - 这真的很糟糕。
1
robert at cotran dot ca
18 年前
上面的 zip_entry_read 是错误的。由于文件是用 popen 打开的,您必须分块读取文件,因此 zip_entry_read 应该读取

function zip_entry_read(&$res, $nbytes)
{
$contents = '';
while (!feof($res['fp'])) {
$contents .= fread($res['fp'], 8192);
}
return $contents;
}

否则,这是一个非常有用的库。谢谢!
2
ohcc at 163 dot com
8 年前
zip 归档文件只有在调用 ZipArchive::close() 之后才会保存到磁盘上。(如果您没有编写该代码,ZipArchive::close 会在脚本结束时自动调用。)

如果您想在将文件添加到 zip 归档文件后删除它,您应该在调用 ZipArchive::close() 之后删除它。否则,文件将在实际添加到归档文件之前被删除,这将导致您的 zip 归档文件无法保存。

<?php
$za
= new ZipArchive();
$za->open('./xc.zip', ZipArchive::CREATE|ZipArchive::OVERWRITE);
$file = './notes.txt';
if(
true === $za->addFile($file)){
unlink($file);
}
if(!
$za->close()){
echo
'failure.';
}
?>
2
ponsho
18 年前
对于 bisqwit at iki dot fi 针对替代函数的解决方案,在尝试读取文件时只有一个问题,那是因为 fread 在处理 popen 时存在一些错误,因此它只加载了 8192 字节,以下是更正后的函数。

<?php

function zip_entry_read(&$res, $nbytes)
{
while (
$s = fgets($res['fp'],1024)) {
$data .= $s;
}
return
$data;
}
?>
0
flominator at gmx dot net
17 年前
@bisqwit at iki dot fi: 如果您使用的是较旧版本的 PHP,此脚本可能只读取前 8192 字节。无论如何,很棒!
0
barbarinasv at interfree dot it
18 年前
由“bisqwit at iki dot fi”编写的函数 zip_entry_read() 必须修改为读取整个文件

<?php
function zip_entry_read(&$res, $nbytes) {
while (!
feof($res['fp'])) {
$contents .= fread($res['fp'], $nbytes);
}
return
$contents;
}
?>
-1
alban dot lopez+php dot net at gmail dot com
16 年前
参见此类以创建、读取信息或提取 ZIP 归档文件。
参见 http://ajaxbrowser.free.fr/ 上的 EasyArchive.class.php 以类似地管理 ZIP、GZIP、BZIP 和 TAR 归档文件。

<?
$ARCHIVE = new zip;

$ARCHIVE->makeZip('./','./toto.zip'); // 创建 ZIP 归档文件
var_export($ARCHIVE->infosZip('./toto.zip'), false); // 获取此 ZIP 归档文件的信息(不包含文件内容)
var_export($ARCHIVE->infosZip('./toto.zip')); // 获取此 ZIP 归档文件的信息(包含文件内容)
$ARCHIVE->extractZip('./toto.zip', './1/'); //

class zip
{
public function infosZip ($src, $data=true)
{
if (($zip = zip_open(realpath($src))))
{
while (($zip_entry = zip_read($zip)))
{
$path = zip_entry_name($zip_entry);
if (zip_entry_open($zip, $zip_entry, "r"))
{
$content[$path] = array (
'Ratio' => zip_entry_filesize($zip_entry) ? round(100-zip_entry_compressedsize($zip_entry) / zip_entry_filesize($zip_entry)*100, 1) : false,
'Size' => zip_entry_compressedsize($zip_entry),
'NormalSize' => zip_entry_filesize($zip_entry));
if ($data)
$content[$path]['Data'] = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
zip_entry_close($zip_entry);
}
else
$content[$path] = false;
}
zip_close($zip);
return $content;
}
return false;
}
public function extractZip ($src, $dest)
{
$zip = new ZipArchive;
if ($zip->open($src)===true)
{
$zip->extractTo($dest);
$zip->close();
return true;
}
return false;
}
public function makeZip ($src, $dest)
{
$zip = new ZipArchive;
$src = is_array($src) ? $src : array($src);
if ($zip->open($dest, ZipArchive::CREATE) === true)
{
foreach ($src as $item)
if (file_exists($item))
$this->addZipItem($zip, realpath(dirname($item)).'/', realpath($item).'/');
$zip->close();
return true;
}
return false;
}
private function addZipItem ($zip, $racine, $dir)
{
if (is_dir($dir))
{
$zip->addEmptyDir(str_replace($racine, '', $dir));
$lst = scandir($dir);
array_shift($lst);
array_shift($lst);
foreach ($lst as $item)
$this->addZipItem($zip, $racine, $dir.$item.(is_dir($dir.$item)?'/':''));
}
elseif (is_file($dir))
$zip->addFile($dir, str_replace($racine, '', $dir));
}
}
?>
-1
xsign dot dll at clansuite dot com
15 年前
如果你只想提取 zip 文件中的某个文件,可以使用这个函数。也许它能帮上忙

<?php
/**
* 此方法将 zip 档案中的目录解压缩
*
* @author Florian 'x!sign.dll' Wolf
* @license LGPL v2 或更高版本
* @link http://www.xsigndll.de
* @link http://www.clansuite.com
*/

function extractZip( $zipFile = '', $dirFromZip = '' )
{
define(DIRECTORY_SEPARATOR, '/');

$zipDir = getcwd() . DIRECTORY_SEPARATOR;
$zip = zip_open($zipDir.$zipFile);

if (
$zip)
{
while (
$zip_entry = zip_read($zip))
{
$completePath = $zipDir . dirname(zip_entry_name($zip_entry));
$completeName = $zipDir . zip_entry_name($zip_entry);

// 遍历路径以创建不存在的目录
// 这不适用于空目录!它们将在下面创建
if(!file_exists($completePath) && preg_match( '#^' . $dirFromZip .'.*#', dirname(zip_entry_name($zip_entry)) ) )
{
$tmp = '';
foreach(
explode('/',$completePath) AS $k)
{
$tmp .= $k.'/';
if(!
file_exists($tmp) )
{
@
mkdir($tmp, 0777);
}
}
}

if (
zip_entry_open($zip, $zip_entry, "r"))
{
if(
preg_match( '#^' . $dirFromZip .'.*#', dirname(zip_entry_name($zip_entry)) ) )
{
if (
$fd = @fopen($completeName, 'w+'))
{
fwrite($fd, zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)));
fclose($fd);
}
else
{
// 我们认为这是一个空目录
mkdir($completeName, 0777);
}
zip_entry_close($zip_entry);
}
}
}
zip_close($zip);
}
return
true;
}

// 解压缩 zip 文件中路径的调用
extractZip( 'clansuite.zip', 'core/filters' );
?>
-4
strefrextor at gmail [.] com
14 年前
我的基本解压缩 zip 文件函数

<?php
function ezip($zip, $hedef = '')
{
$root = $_SERVER['DOCUMENT_ROOT'];
$zip = zip_open($root . $zip);
while(
$zip_icerik = zip_read($zip)):
$zip_dosya = zip_entry_name($zip_icerik);
if(
strpos($zip_dosya, '.')):
$hedef_yol = $root . $hedef . 'x/'.$zip_dosya;
touch($hedef_yol);
$yeni_dosya = fopen($hedef_yol, 'w+');
fwrite($yeni_dosya, zip_entry_read($zip_icerik));
fclose($yeni_dosya);
else:
@
mkdir($root . $hedef . 'x/'.$zip_dosya);
endif;
endwhile;
}

ezip('files.zip', 'unzip_files/');
?>
To Top