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;
}
不要なファイルの読み取りを避けてください:特定の拡張機能を備えたディレクトリまたはファイルが必要なプロセスのみが必要です。
オンデマンドの読み込み:大規模なファイルの場合、 zip_entry_read($ entry、zip_entry_filesize($ entry))を使用して一度に読み込みませんが、ストリーミング読み取りを使用します。
バッチ操作:最終操作にデータベースまたは外部サービスが含まれる場合、バッファリング結果を検討し、バッチで送信します。
zip_read()関数を使用してzipファイルを処理することはziparchiveほど直感的ではありませんが、構造制御要件が高いシナリオでは依然として非常に実用的です。パス文字列を分析することにより、マルチレイヤーネストされたディレクトリを効果的に処理し、コンテンツをサーバー指定パスに安全に抽出できます。適切なセキュリティとパフォーマンスの最適化測定を組み合わせて、このアプローチは、複雑なzipファイル処理ロジックを構築するための強力なツールのままです。