Mime Types.
ダウンロード・カウンタ(1998/10/9)
次にダウンロードカウンタなんかを作ってみましょうか。あなたのサイトから何らかのファイル等をダウンロード出来るようにしている場合に、どれくらいダウンロードされたかをカウントしてみようというモノです。また、必ずしもダウンロード回数のカウントだけでなく参照カウンタとしても利用できます。画像ファイル(JPEGやGIF等)を公開しているときに、どれくらいの人がそれを見てくれたかをカウントする目的にも使えます。
ダウンロード・カウンタもよくあるアクセス・カウンタと仕組みとしては全く同じモノです。唯一違いがあるとすればアクセス・カウンタの場合はカウンタのグラフィックス或いはカウンタ埋め込み済みのHTMLを出力しますが、ダウンロード・カウンタの場合はダウンロードするファイルそのものをバイナリで出力することです。バイナリで出力する前にカウントを増やすというだけです。ですからperlでの基本的な骨組みはアクセス・カウンタと何ら変わりません。
まずはABC.LZHというファイルをダウンロード出来るサイトにダウンロード・カウンタを設けるとして話を進めましょう。当然何らかのページからABC.LZHにHTMLでハイパーリンクをはることになります。ブラウザでABC.LZHへのハイパーリンクをクリックするとダウンロード・カウンタであるperlで書かれたcgiプログラムが動き出すようになっている必要があります。まずここで1つ選択を迫られます。ダウンロードするファイルはどんな拡張子になるか判りません。今の場合だと拡張子は.LZHです。どんな拡張子のファイルでもcgiプログラムとしてhttpdが起動してくれるのであれば全く問題ありません。ですが、httpdがcgiプログラムとして認識してくれる拡張子が.cgiに限定されているという場合にはそれに従うしかありません。この辺の事情はISPがどのようにサーバを設定しているかによってくるので予め調べる等して知っておく必要があります。もっともHTMLでハイパーリンクする先のファイル名が"ABC.LZH"になるか"なんとか.cgi"になるかの違いだけなんですけどもね。
それでは具体的な話に入ります。perlで書くcgiプログラムの名前ですが、httpdが任意の拡張子をcgiプログラムとして起動出来る場合にはABC.LZHという名前にしてしまいましょう。一見したところ直接ABC.LZHにリンクしていて単にそれをブラウザがダウンロードし始めるように見えますが、実はABC.LZHはperlで書かれたcgiプログラムで本当にダウンロードされるファイルは別名でサーバ上に置いてあるというわけです。しかしこれは.LZHという拡張子のファイルをcgiプログラムとして起動できる場合でないと実現できません。それが出来ない場合はHTMLで"なんとか.cgi"へのハイパーリンクにするしか手がありません。
ダウンロード・カウントを記録するファイルをdownload.countとします。また実際のダウンロード対象となるファイルはdownload.fileとします。perlで書くcgiプログラムはABC.LZHとします。.LZHをcgiプログラムとして設定出来ないサーバの場合は仕方がないのでdownload.cgi等とします。perlで書くcgiプログラムは結構シンプルにまとまります。
#! /usr/local/bin/perl
$download_file = './download.file'; # ダウンロードするファイル名
$count_file = './download.count'; # カウントファイル名# カウンタの読み込み
open( COUNT, $count_file );
$count = <COUNT>;
close( COUNT );# インクリメント
$count++;# カウンタの書き込み
open( COUNT, ">$count_file" );
print COUNT "$count";
close( COUNT );# ダウンロードファイルの読み込み
$/ = ''; # セパレータなし
open( DL, $download_file );
$file = <DL>;
close( DL );print "Content-type; application/octet-stream\n\n"; # httpdにヘッダ出力
print "$file"; # ファイル出力
cgiプログラムとしてはこれだけです。アクセス・カウンタよりもやることが少ないので短くなっています。見るべき点は最後の方です。プログラムの最後にprintが2つ使われています。httpdにヘッダ出力というコメントのついている行を見て下さい。アクセス・カウンタの場合でもContent-type; text/htmlというヘッダをまず最初に出力しました。今度のダウンロード・カウンタの場合はContent-type; application/octet-streamとなっています。これもMIMEタイプです。text/htmlはHTMLテキストを示すMIMEタイプでしたが、application/octet-streamは単なるバイナリ・データを示すMIMEタイプです。アクセス・カウンタと違い、今回のダウンロード・カウンタはダウンロードさせるファイルをバイナリで出力してやるのでこのようにMIMEタイプを変えておかないといけません。 もしファイルをダウンロードさせるのではなく画像ファイルをブラウザに表示させたいのであれば適宜image/jpegやimage/gif等に変える必要があります。画像ファイルであってもバイナリで出力することに変わりはなく、またブラウザに出力される前にhttpdが介在することも同じなのですが、折角ブラウザに画像ファイルのデータが配信されてもブラウザがそれを画像だと認識しないことには表示するという行為を行ってくれません。そのためにimage/jpeg等のMIMEタイプを出力してやる必要があります。
もう1つ。セパレータなしというコメントの行です。ここに変な名前の変数が出てきています。$/という変数ですが、perlは使用目的が予め定められている変数として組み込み変数というモノがあり、この変数$/も正に組み込み変数です。組み込み変数は色々な種類がありますが見分けるのは簡単で、$に続けて記号が1文字だけの変数があったらそれは組み込み変数です。今の場合は/ですね。この組み込み変数はファイルから入力する時に何で区切って読み込むかを指定するモノです。特に何も代入を行っていない場合は最初から改行が変数$/に代入済みとなっています。今はファイルを区切らずに丸ごと変数$fileに読み込みたいので、組み込み変数$/に空文字列を代入しています。これでファイルが区切られることなく丸ごと変数$fileに読み込まれます。もしこの組み込み変数$/に改行文字が代入されていると、<DL>でファイルから読み込むときに改行コードが現れた時点で読み込みを終え、そこまでしか変数$fileに読み込まれません。
さてasciiモードでサーバにcgiプログラムを転送し、cgiプログラムと同じディレクトリにdownload.fileとdownload.countというファイルを置きます。download.countは中身が空っぽのファイルです。permissionを付けるのもお忘れなく。cgiプログラムはnobodyの--xもしくはr-x、download.fileはnobodyのr--、download.countはnobodyのrw-の属性が必要です。残りは.htaccessを用意してやることくらいです。ABC.LZHというファイル名のcgiプログラムにするのであれば以下のようにしておかないといけませんね。
AddType application/x-httpd-cgi .LZH
これでABC.LZHをcgiプログラムとして起動してもらえます。permissionはnobodyのr--でOKです。後はHTMLからABC.LZHにリンクをはるだけでおしまい。さて、うまくいったでしょうか。カウントがうまくいっているとして、果たしてどうやってカウンタを見ればよいでしょうか? telnetでログインしている時はcatコマンドで直接download.countを表示させてもいいのですが、ブラウザで見るにはどうしましょう? 見た目にこだわらないのであれば単にブラウザからカウント・ファイルのURLを指定すればOKです。もしブラウザで表示出来なければ.htaccessにもう1行追加してやる必要があります。
AddType text/plain .count
これでOKでしょう。