PHP でディレクトリを [再帰的に] Zip 圧縮する方法は? [重複] 質問する

PHP でディレクトリを [再帰的に] Zip 圧縮する方法は? [重複] 質問する

ディレクトリは次のようになります。

home/
    file1.html
    file2.html
Another_Dir/
    file8.html
    Sub_Dir/
        file19.html

PHPMyAdminで使用されているのと同じPHP Zipクラスを使用していますhttp://trac.seagullproject.org/browser/branches/0.6-bugfix/lib/other/Zip.phpファイルだけではなくディレクトリを zip 圧縮する方法がよくわかりません。 これまでのところ、次のようになっています。

$aFiles = $this->da->getDirTree($target);
/* $aFiles is something like, path => filetime
Array
(
    [home] => 
    [home/file1.html] => 1251280379
    [home/file2.html] => 1251280377
    etc...
)

*/
$zip = & new Zip();
foreach( $aFiles as $fileLocation => $time ){
    $file = $target . "/" . $fileLocation;
    if ( is_file($file) ){
        $buffer = file_get_contents($file);
        $zip->addFile($buffer, $fileLocation);
    }
}
THEN_SOME_PHP_CLASS::toDownloadData($zip); // this bit works ok

しかし、ダウンロードした対応するzipファイルを解凍しようとすると、「操作は許可されていません」というメッセージが表示されます

このエラーは、Mac で解凍しようとしたときにのみ発生します。コマンドラインで解凍すると、ファイルは正常に解凍されます。ダウンロード時に特定のコンテンツ タイプを送信する必要がありますか? 現在は「application/zip」です。

ベストアンサー1

これは、任意のファイルまたはディレクトリを再帰的に圧縮できる単純な関数です。zip 拡張子をロードするだけで済みます。

function Zip($source, $destination)
{
    if (!extension_loaded('zip') || !file_exists($source)) {
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true)
    {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file)
        {
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
                continue;

            $file = realpath($file);

            if (is_dir($file) === true)
            {
                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            }
            else if (is_file($file) === true)
            {
                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
            }
        }
    }
    else if (is_file($source) === true)
    {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}

次のように呼び出します:

Zip('/folder/to/compress/', './compressed.zip');

おすすめ記事