通过ZipArchive php获取损坏或空的zip文件

7
以下是代码:

虽然没有错误,但是按照下面的代码下载的zip文件为空或损坏,大小始终约为200字节。也就是说,我无法打开那个zip文件。同时,ZipArchive::getStatusString() 也显示“没有错误”。

public function getzip(){
    global $config;
    $files=array();
    if(isset($_COOKIE['hashes'])){
        $hashes=explode(',',$_COOKIE['hashes']);
        for ($i=0; $i <count($hashes); $i++) {
            array_push($files,$config["domain"]."/download/".$hashes[$i]); 
        }
    }
    if(count($files)){
        $zipname='basket.zip';
        $zip = new ZipArchive;
        $zip->open($zipname,ZipArchive::CREATE);
        foreach ($files as $key=>$value ) {
            $zip->addFile($value);
        }
        $status=$zip->getStatusString();
        $zip->close();

    if(!$zipname)
    {
        echo "Nothing in Basket";
    }
    else
    {   header('Content-Description: File Transfer');
        header('Content-Type: application/zip');
        header('Content-Disposition:attachment; filename='.basename($zipname));
        header('Content-Length:'.filesize($zipname));
        readfile($zipname);
    }
}

它给了我一个错误。这意味着$zipname目录没有被创建。 但是我没有收到“购物篮为空”的消息,而是下载了一个zip文件。 - Durgesh Suthar
8个回答

5

尝试在$zip->close();之前获取完整的文件路径和名称。

$filename = $zip->filename;

在读取文件和获取文件大小时,使用它来代替$zipname


@Pony 请再检查一下.. 我还是遇到了同样的问题。 我认为文件目录没有被创建。 同时,我已经检查过 'var_dump($filename)' 显示了确切的路径。 - Durgesh Suthar
在调用 $zip->close() 之前,您是否分配了这个变量? - nice ass

3
这是我最好的猜测。问题出在你的数组$files中存储的值可能不是实际文件的路径。
请注意:你不能将URL传递给$zip->addfile(),需要使用实际文件。

1
尽管这个问题已经被解决,但我会发布我发现的有关如何创建损坏的压缩文件的信息:
在创建zip归档文件时,您通常会使用echo/print_r命令进行调试。 如果您不清除这些命令的输出,则生成的zip文件将是损坏的。
以下是基于此问题的示例:
public function getzip(){
    global $config;
    $files=array();
    if(isset($_COOKIE['hashes'])){
        $hashes=explode(',',$_COOKIE['hashes']);
        for ($i=0; $i <count($hashes); $i++) {
            array_push($files,$config["domain"]."/download/".$hashes[$i]); 
        }
    }
    if(count($files)){
        $zipname='basket.zip';
        $zip = new ZipArchive;
        $zip->open($zipname,ZipArchive::CREATE);
        foreach ($files as $key=>$value ) {
            $zip->addFile($value);
        }
        $status=$zip->getStatusString();
        $zip->close();

    if(!$zipname)
    {
        echo "Nothing in Basket";
    }
    else
    {   
        // to fix your corrupt zip file, remove this line.
        echo 'THIS IS AN EXAMPLE DEBUG: ' . $zipname;
        header('Content-Description: File Transfer');
        header('Content-Type: application/zip');
        header('Content-Disposition:attachment; filename='.basename($zipname));
        header('Content-Length:'.filesize($zipname));
        readfile($zipname);
    }
}

删除 echo 和 print_r 语句对我有用...谢谢 :) - Ashutosh Gupta

1
即使原始问题已经解决,我还是想为这个帖子做出贡献,因为我刚刚花了几个小时处理类似的问题。事实证明,在执行$zip->close()时,所有文件都需要存在,无论何时使用$zip->addFile()添加它们。
因此,如果您创建临时文件,将它们添加到zip文件中,然后在使用close()之前删除它们,则可能会得到一个空/损坏的归档文件。

1

可能这对 OP 没有用,但当我更改虚拟服务器时,我遇到了这个问题。我不知道服务器设置发生了什么变化,但 zip 开始制作空的压缩包。

经过一些研究和测试,我发现我所需要做的就是添加文件名(我不知道为什么在旧服务器上可以工作)作为第二个参数:
$zip->addFile($value, $zipname); // 在这种情况下是 $zipname

我遇到的另一个问题是我的 memory_limit 太低了。

希望这能帮到你!


0
在我的情况下,问题出在将'/'的值传递给ZipArchive::addGlob()方法中的add_path选项上:
    $zipArchive->addGlob($tmpFolder . DIRECTORY_SEPARATOR ."*", 
                         0, 
                         ['add_path' => '/', 'remove_all_path' => true]);

移除那部分对我解决了问题:

    $zipArchive->addGlob($tmpFolder . DIRECTORY_SEPARATOR ."*", 
                         0, 
                         ['remove_all_path' => true]);

0

我通过将代码移动到与我想要添加到Zip归档文件的文件相同的文件夹中解决了相同的问题。


0
在我的情况下,问题出在将文件名作为第二个参数传递的地方。 我相信由于代码是在Linux服务器上执行的,文件路径中的“/”导致在Windows中打开zip文件时出现问题。将文件名作为第二个参数提供解决了这个问题。
if( file_exists($FILEPATH) && is_readable($FILEPATH) && filesize($FILEPATH) > 0 ){
          if ( $zip->addFile($FILEPATH, $FILENAME) != TRUE ) {
              die("Could not open $FILENAME");
          }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接