zipファイルの作り方

CGIテクニック集トップへ





概要

複数のファイルを一つのzipファイルにアーカイブしてダウンロードできるようにします。ファイルリスト3画像ダウンロードメッセージボード5等で利用されています。

必用な処理

  1. PerlのPackage Archive::Zipを読み込む
  2. zipファイルを作成
  3. それぞれのファイルをzipのメンバーとして登録する
  4. 作成したzipファイルをディスクに書き出す
  5. ステータスをチェックしてエラー処理をする
  6. 作成したzipファイルをブラウザ上に出力する

サンプルコード

 use Archive::Zip;
 
 my @filelist = qw(a.jpg b.txt c.zip d.jpg);
 
 my $zip = Archive::Zip->new();
 
 foreach ($_){
   $zip->addFile("$_");
 }
 
 my $zipfile = "file.zip";
 my $status = $zip->writeToFileNamed("$zipfile");
 
 if ($status != 'AZ_OK') {
     unlink("$zipfile") if (-e "$zipfile");
     print "Content-Type:text/html\n\n";
     print "$zipfileが作成されません";
     exit;
 }
 
 print "Location: $zipfile\n\n";

コードの解説

 use Archive::Zip;

PerlのPackage、Archive::Zipを読み込みます。

 my @filelist = qw(a.jpg b.txt c.zip d.jpg);

ファイルのリストを作成。a.jpg, b.txt等は既に存在するものと仮定します。存在するかどうかわからない場合は適切なエラー処理が後に必要になります。

 my $zip = Archive::Zip->new();

zipファイルをメモリ上に作成します。同時にオブジェクト$zipを作成。この$zipに対して処理をしていきます。

 foreach ($_){
   $zip->addFile("$_");
 }

それぞれのファイルをメモリ上のzipファイルに追加していきます。Archive::Zipのドキュメントでは以下のような配列を受け付けると書いていますが

 $zip->addFile(@filelist);

実際にはできませんでした。バージョンによって違うのかもしれません。したがって一つずつaddFileで追加していきます。

 my $zipfile = "file.zip";
 my $status = $zip->writeToFileNamed("$zipfile");

zipファイルをディスクに書き出します。ここでのファイル名はfile.zipになっています。書き出しが成功したかをチェックするために$status変数にステータスを挿入します。

 if ($status != 'AZ_OK') {
     unlink("$zipfile") if (-e "$zipfile");
     print "Content-Type:text/html\n\n";
     print "$zipfileが作成されません";
     exit;
 }

成功した場合は$statusにAZ_OKが入ります。そうでない場合にはエラーとして処理を終了します。この時ファイルがディスク上に作成されているかわからないので作成されていれば失敗したファイルなので削除します。ステータスコードには、

 AZ_OK (0)           : 全てが正常
 AZ_STREAM_END (1)   : ストリームリードが正常終了
 AZ_ERROR (2)        : 何かしらの一般エラー
 AZ_FORMAT_ERROR (3) : zipファイル読み込み時にフォーマットエラー
 AZ_IO_ERROR (4)     : IOエラー

があります。

 print "Location: $zipfile\n\n";

Locationタグを利用してディスク上のzipファイルを自動的にダウンロードするようにします。

関連するCGIテクニック

サーバー上の古いテンポラリファイルを自動削除
File::Findを使って複数ディレクトリ内の古いテンポラリファイルを自動削除