4

我有一个包含一个文件夹的 zip 文件,其中包含更多文件夹和文件,如下所示:

myfile.zip
-firstlevel
--folder1
--folder2
--folder3
--file1
--file2

现在,我想使用 PHPs ZipArchive 提取此文件,但没有“第一级”文件夹。目前,结果如下所示:

目的地/第一
级/文件夹1 目的地/第一级/文件夹2
...

我想要的结果如下所示:

目的地/文件夹1
目的地/文件夹2
...

我试过 extractTo,它产生第一个提到的结果,和 copy(),正如这里所建议的,但这似乎根本不起作用。

我当前的代码在这里:

if($zip->open('myfile.zip') === true) {
        $firstlevel = $zip->getNameIndex(0);
        for($i = 0; $i < $zip->numFiles; $i++) {
                $entry = $zip->getNameIndex($i);
                $pos = strpos($entry, $firstlevel);
                if ($pos !== false) {
                        $file = substr($entry, strlen($firstlevel));
                        if(strlen($file) > 0){
                                $files[] = $file;
                        }
                }
        }
        //attempt 1 (extractTo):
        //$zip->extractTo('./test', $files);

        //attempt 2 (copy):
        foreach($files as $filename){
                 copy('zip://'.$firstlevel.'/'.$filename, 'test/'.$filename);
        }
}

我怎样才能达到我想要的结果?

4

1 回答 1

1

看看我的 Quick Unzipper 脚本。不久前,我在将大型 zip 文件上传到服务器时写了这个供个人使用。这是一个备份,使用 FTP 可以永久保存 1,000 个文件,因此使用 zip 文件更快。我使用 Git 和所有东西,但我没有其他选择。我将此 php 文件放在我想要文件的目录中,并将 zip 文件放在同一目录中。对于我的脚本,它们都必须在同一个目录中运行。这是一种简单的方法来保护它以满足我的需要,因为我需要的所有东西都在同一个目录中。

快速解压器:https ://github.com/incomepitbull/QuickUnzipper/blob/master/unzip.php

我链接了该文件,因为我没有展示 repo,只是显示解压缩的代码。使用现代版本的 PHP,您的设置中不应该包含任何内容。所以你不需要做任何服务器配置更改来使用它。

这是它使用的 ZipArchive 类的 PHP 文档:http: //php.net/manual/en/class.ziparchive.php

没有任何包含的方法可以做你想做的事,这是一种耻辱。所以我会将文件解压缩到临时目录,然后使用另一个函数将内容复制到您想要的位置。所以在使用 ZipArchive 的时候,如果是未知的,则需要返回第一项来获取文件夹名称。如果该文件夹是已知的,即:每次都使用相同的讨厌的文件夹名称,那么您可以硬编码该名称。

我已经让它从索引中返回第一个项目。因此,如果您总是有一个包含 1 个文件夹的 zip,以及该文件夹中的所有内容,这将起作用。但是,如果您有一个 zip 文件,但没有将所有内容合并到 1 个文件夹中,它就会失败。我添加的代码将解决您的问题。您将需要添加更多逻辑来处理其他情况。

此外,当我们将旧目录提取到临时目录进行“处理”时,您仍然会留下旧目录。所以我也包含了删除它的代码。

注意:代码使用大量 if 来显示处理步骤,并打印一条消息以用于测试目的。您需要根据需要对其进行修改。

<?php
public function copyDirectoryContents($source, $destination, $create=false)
{
    if ( ! is_dir($source) ) {
        return false;
    }

    if ( ! is_dir($destination) && $create === true ) {
        @mkdir($destination);
    }

    if ( is_dir($destination) ) {
        $files = array_diff(scandir($source), array('.','..'));
        foreach ($files as $file)
        {
            if ( is_dir($file) ) {
                copyDirectoryContents("$source/$file", "$destination/$file");
            } else {
                @copy("$source/$file", "$destination/$file");
            }
        }
        return true;
    }
    return false;
}

public function removeDirectory($directory, $options=array())
{
    if(!isset($options['traverseSymlinks']))
        $options['traverseSymlinks']=false;
    $files = array_diff(scandir($directory), array('.','..'));
    foreach ($files as $file)
    {
        if (is_dir("$directory/$file"))
        {
            if(!$options['traverseSymlinks'] && is_link(rtrim($file,DIRECTORY_SEPARATOR))) {
                unlink("$directory/$file");
            } else {
                removeDirectory("$directory/$file",$options);
            }
        } else {
            unlink("$directory/$file");
        }
    }
    return rmdir($directory);
}


$file = dirname(__FILE__) . '/file.zip';        // full path to zip file needing extracted
$temp = dirname(__FILE__) . '/zip-temp';        // full path to temp dir to process extractions
$path = dirname(__FILE__) . '/extracted';       // full path to final destination to put the files (not the folder)

$firstDir = null;       // holds the name of the first directory

$zip = new ZipArchive;
$res = $zip->open($file);
if ($res === TRUE) {
    $firstDir = $zip->getNameIndex(0);
    $zip->extractTo($temp);
    $zip->close();
    $status = "<strong>Success:</strong> '$file' extracted to '$temp'.";
} else {
    $status = "<strong>Error:</strong> Could not extract '$file'.";
}

echo $status . '<br />';

if ( empty($firstDir) ) {
    echo 'Error: first directory was empty!';
} else {
    $firstDir = realpath($temp . '/' . $firstDir);
    echo "First Directory: $firstDir <br />";
    if ( is_dir($firstDir) ) {
        if ( copyDirectoryContents($firstDir, $path) ) {
            echo 'Directory contents copied!<br />';
            if ( removeDirectory($directory) ) {
                echo 'Temp directory deleted!<br />';
                echo 'Done!<br />';
            } else {
                echo 'Error deleting temp directory!<br />';
            }
        } else {
            echo 'Error copying directory contents!<br />';
        }
    } else {
        echo 'Error: Could not find first directory';
    }
}
于 2015-01-26T11:38:18.460 回答