現在の位置: ホーム> 最新記事一覧> zip_read()関数を使用して、マルチレイヤーネストディレクトリを含むzip圧縮パッケージを効率的に処理する方法

zip_read()関数を使用して、マルチレイヤーネストディレクトリを含むzip圧縮パッケージを効率的に処理する方法

M66 2025-06-15

PHPでZIPファイルを使用することは、特にコンテンツを抽出したり、圧縮パッケージからファイル構造を読み取る必要がある場合に共通のタスクです。 ZIP_READ()関数は、Ziparchiveクラスの外でZIPファイルを処理する別の方法です。 zip_open()zip_entry_read()などの関数でよく使用されます。これらの機能は低レベルですが、特にマルチレイヤーネストディレクトリを含むZIPファイルを扱う場合、ZIPファイル構造をより深く把握したい開発者にとって、依然として非常に重要です。

基本的な使用方法

まず、 zip_open()を使用してzipファイルを開き、 zip_read()を使用して各エントリを反復する必要があります。以下は基本構造です。

 $zip = zip_open("nested_directories.zip");

if (is_resource($zip)) {
    while ($entry = zip_read($zip)) {
        $entryName = zip_entry_name($entry);
        echo "Entry: $entryName\n";
    }
    zip_close($zip);
}

このコードスニペットは、すべてのエントリ(ディレクトリとファイルを含む)をzipファイルにリストすることができますが、リストだけでは十分ではありません。ネストされた構造をより深く扱う必要があります。

ネストされたディレクトリ構造を識別します

ZIPファイルのネストされたディレクトリには、実際のファイルシステムのような「ツリーのような」構造がありません。たとえば、各ディレクトリまたはファイルはパス文字列として表されます。

 photos/
photos/vacation/
photos/vacation/beach.jpg
documents/report.docx

したがって、 /に基づいてファイルパスの深さを判断する必要があります。各レイヤーは、Simple Exploit()で分析できます。

 $depth = substr_count($entryName, '/');

これは、ディレクトリレベルに応じて特定の操作を実行する必要がある場合に非常に便利です。

ファイルを抽出し、ディレクトリ構造を保持します

zipファイルの内容を指定されたディレクトリに抽出し、そのディレクトリ構造を保持するために、 zip_entry_read()およびfile_put_contents()と組み合わせて実行できます。以下に示すように:

 $zip = zip_open("nested_directories.zip");

$extractPath = "extracted/";

if (is_resource($zip)) {
    while ($entry = zip_read($zip)) {
        if (zip_entry_open($zip, $entry, "r")) {
            $entryName = zip_entry_name($entry);
            $fullPath = $extractPath . $entryName;

            // それがディレクトリの場合,必ず作成してください
            if (substr($entryName, -1) === '/') {
                if (!is_dir($fullPath)) {
                    mkdir($fullPath, 0755, true);
                }
            } else {
                // ファイルの場合,以前のディレクトリが存在することを確認してください
                $dir = dirname($fullPath);
                if (!is_dir($dir)) {
                    mkdir($dir, 0755, true);
                }

                $content = zip_entry_read($entry, zip_entry_filesize($entry));
                file_put_contents($fullPath, $content);
            }

            zip_entry_close($entry);
        }
    }
    zip_close($zip);
}

上記のコードは、完全なネストされた構造抽出関数を実装し、ディレクトリの作成とファイルの書き込みを処理し、元の構造が変化しないようにします。

実用的なアプリケーションの例

ZIPアップロード機能を提供するために、Webサイト( https://m66.net/uploadなど)を開発したと想像してください。ユーザーがアップロードしたzipファイルには、複雑なマルチレイヤーネストディレクトリが含まれる場合があります。これらのファイルをさらに処理するためにこれらのファイルを一時ディレクトリに安全に再圧縮するために、最初に上記のコードでコンテンツを抽出し、次に処理のためにターゲットフォルダーを通過できます。

パストラバーサルの脆弱性を回避するには、 ../../../etc/ passwdを含む悪意のあるzipなど)、パスステッチ後にセキュリティ検証を実行する必要があります。

 $realBase = realpath($extractPath);
$realUserPath = realpath($fullPath);

if (strpos($realUserPath, $realBase) !== 0) {
    // 違法な道,飛び越える
    continue;
}

パフォーマンス最適化の提案

  1. 不要なファイルの読み取りを避けてください:特定の拡張機能を備えたディレクトリまたはファイルが必要なプロセスのみが必要です。

  2. オンデマンドの読み込み:大規模なファイルの場合、 zip_entry_read($ entry、zip_entry_filesize($ entry))を使用して一度に読み込みませんが、ストリーミング読み取りを使用します。

  3. バッチ操作:最終操作にデータベースまたは外部サービスが含まれる場合、バッファリング結果を検討し、バッチで送信します。

要約します

zip_read()関数を使用してzipファイルを処理することはziparchiveほど直感的ではありませんが、構造制御要件が高いシナリオでは依然として非常に実用的です。パス文字列を分析することにより、マルチレイヤーネストされたディレクトリを効果的に処理し、コンテンツをサーバー指定パスに安全に抽出できます。適切なセキュリティとパフォーマンスの最適化測定を組み合わせて、このアプローチは、複雑なzipファイル処理ロジックを構築するための強力なツールのままです。