4

次のように、複数のフォルダーとファイルを含む 1 つのフォルダーを含む zip ファイルがあります。

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

ここで、PHP ZipArchive を使用してこのファイルを抽出しますが、「firstlevel」フォルダーは使用しません。現時点では、結果は次のようになります。

宛先/最初のレベル/フォルダー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 では数千のファイルが永遠にかかるため、zip ファイルを使用した方が高速でした。私は Git などを使用していますが、他に選択肢がありませんでした。このphpファイルをファイルを配置したいディレクトリに配置し、zipファイルを同じディレクトリに配置します。私のスクリプトでは、それらはすべて同じディレクトリで動作する必要があります。必要なものはすべて同じディレクトリにあるので、私のニーズに合わせて簡単に保護できました。

クイックアンジッパー: https://github.com/incomepitbull/QuickUnzipper/blob/master/unzip.php

リポジトリを紹介するのではなく、解凍を行うコードだけを紹介しているので、ファイルをリンクしました。最新バージョンの PHP では、セットアップに含まれていないものは何もないはずです。したがって、これを使用するためにサーバー構成を変更する必要はありません。

これが使用する ZipArchive クラスの PHP Doc は次のとおりです: http://php.net/manual/en/class.ziparchive.php

残念なことに、あなたが望むことを行う方法は含まれていません。したがって、ファイルを一時ディレクトリに解凍し、別の関数を使用して内容を必要な場所にコピーします。そのため、ZipArchive を使用する場合、フォルダー名が不明な場合は、最初のアイテムを返してフォルダー名を取得する必要があります。フォルダーが既知の場合、つまり、毎回同じ厄介なフォルダー名である場合は、名前をハードコーディングできます。

インデックスから最初のアイテムを返すようにしました。そのため、常に1つのフォルダーが含まれるzipがあり、そのフォルダー内のすべてがあれば、これは機能します。ただし、すべてが 1 つのフォルダー内に統合されていない zip ファイルがある場合、失敗します。私が追加したコードは、あなたの質問を処理します。別のケースを処理するには、さらにロジックを追加する必要があります。

また、「処理」のために一時ディレクトリに抽出したときから、古いディレクトリが残ったままになります。そのため、それを削除するコードも含めました。

注: このコードでは、多くの 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 に答える