【PHP実践|実務向け】実務で役立つPHPのZipArchive活用術:ファイル圧縮と動的生成のテクニック

導入

Webアプリケーション開発において、ユーザーに複数のファイルを一括ダウンロードさせたり、バックアップファイルを生成したりする場面は頻繁にあります。PHP標準のZipArchiveクラスを活用すれば、外部ライブラリに依存することなく、高速かつ安全にZIPファイルの操作が可能です。本記事では、基本的な圧縮・展開の方法に加え、実務で重要となる「動的に生成したデータを直接ZIP化する」テクニックを解説します。

基礎知識

ZipArchiveは、PHPのZip拡張モジュール(php-zip)によって提供されるクラスです。これを利用することで、サーバー上のファイルをZIP形式でアーカイブ化したり、逆に既存のアーカイブを解凍したりできます。利用にあたっては、サーバー環境でphp-zip拡張が有効になっていることが前提です。phpinfo()等で確認し、インストールされていない場合はパッケージマネージャーから導入してください。

実装/解決策

実務では、ファイルシステム上の既存ファイルを圧縮するだけでなく、DBから取得したデータをその場でテキストファイルとしてZIPに含めるケースが多々あります。その際、一時ファイルを作成せずにaddFromStringメソッドを使用することで、I/O負荷を抑えた効率的な処理が可能です。

サンプルプログラム

以下のコードは、既存ファイルをアーカイブに追加しつつ、動的に生成したテキストデータを直接ZIPに含め、最後にブラウザ経由でダウンロードさせる一連の流れです。

open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {

// 1. サーバー上の既存ファイルを追加
// 第2引数はZIP内でのパスを指定可能
$zip->addFile(‘./data/report.pdf’, ‘report.pdf’);

// 2. 文字列から動的にファイルを作成して追加(一時ファイル作成不要)
$content = “これは動的に生成されたログファイルです。\n作成日時: ” . date(‘Y-m-d H:i:s’);
$zip->addFromString(‘logs/dynamic_log.txt’, $content);

$zip->close();
} else {
die(‘ZIPファイルの作成に失敗しました。’);
}

// ブラウザへダウンロードさせるためのヘッダー出力
header(‘Content-Type: application/zip’);
header(‘Content-Disposition: attachment; filename=”download.zip”‘);
header(‘Content-Length: ‘ . filesize($zipPath));
header(‘Pragma: no-cache’);

// ファイルを出力して削除
readfile($zipPath);
unlink($zipPath); // 一時ファイルは必ず削除する
exit;

応用・注意点

1. 一時ファイルの管理:
上記サンプルではtempnamを使用して一時ファイルを作成していますが、処理終了後にunlinkで必ず削除してください。これを怠るとサーバーのディスク容量を圧迫する原因になります。

2. 日本語ファイル名の文字化け:
ZIPファイル内のファイル名に日本語(マルチバイト文字)が含まれる場合、Windowsの標準解凍ソフトで文字化けが発生することがあります。必要に応じてファイル名をUTF-8からCP932へ変換する等の対策が必要になる場合がありますが、近年はUTF-8対応が進んでいるため、まずはUTF-8で実装し、検証することをお勧めします。

3. メモリ制限:
非常に大きなサイズのファイルを扱う場合、PHPのmemory_limitに抵触する可能性があります。大量のファイルを扱う場合は、逐次処理やキューイングを検討してください。

4. エラーハンドリング:
openメソッドの戻り値だけでなく、addFileが正常に機能したかを確認するには、ファイルが存在しているか事前のチェックを徹底しましょう。実務では予期せぬパス指定によるエラーが最も多いため、パスのバリデーションを厳格に行うことが重要です。

タイトルとURLをコピーしました