Archive::Zip を CGI で使う
Archive::Zip
を使って、zip ファイルから jpg ファイルを取り出して、ブラウザに返す CGI の例です。
(ただしここでは、カレントディレクトリに Img0051.zip
というファイルがあり、その中には DSCN1182.JPG
というファイルが格納されているものとします。)
#! /usr/bin/perl use Archive::Zip; my $ZIP_FILE_NAME = "Img0051.zip"; my $MEMBER_FILE_NAME = "DSCN1182.JPG"; my $zip; $zip = Archive::Zip->new(); $zip->read($ZIP_FILE_NAME); print "Content-type: image/jpeg\n\n"; print $zip->contents($MEMBER_FILE_NAME);
read
関数で zip ファイルを指定する際や、contents
関数でメンバファイルの中身を取り出す際には、それらがうまく行ったかどうかのチェックがほんとうは必要です。ここでは端折ってます。
それ以外にもこのプログラムには問題があって、print $zip->contents($MEMBER_FILE_NAME);
のところが、一旦 DSCN1182.JPG
の中身を全部メモリに溜め込んで、それを print
文で吐き出すという仕組みになってしまっています。DSCN1182.JPG
のサイズが非常に大きい場合に、Perl にそのぶんのメモリを用意させることになります。
次の例では、DSCN1182.JPG
の内容をちょっとづつ読んでは吐き出すようにしています。
#! /usr/bin/perl use Archive::Zip qw(:CONSTANTS); use strict; my $ZIP_FILE_NAME = "Img0051.zip"; my $MEMBER_FILE_NAME = "DSCN1182.JPG"; my ($zip, $member, $bufferRef); $zip = Archive::Zip->new(); $zip->read($ZIP_FILE_NAME); $member = $zip->memberNamed($MEMBER_FILE_NAME); $member->desiredCompressionMethod(COMPRESSION_STORED); $member->rewindData(); print "Content-type: image/jpeg\n\n"; while (! $member->readIsDone()) { ($bufferRef) = $member->readChunk(); print $$bufferRef; } $member->endRead();
「ちょっとづつ読んでは吐き出す」の「ちょっとづつ」がどれくらいの大きさなのか、は次のようにするとわかります。
%perl -e "use Archive::Zip; print Archive::Zip::chunkSize()" 32768
デフォルトでは、32768 バイト (32KB) のようです。