Perl Perl_2
Perl 「 モジュール 」 CGI.pm フォーム ファイルアップロードの基本処理 (0x109)
目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x109 回。
CGI.pm で作成した、HTML フォームのファイルアップロードフィールドで、ローカルファイルをアップロードするための基本的な処理を確認する。
アップロードフィールドの再確認
前回 (0x108) で確認した通り、メソッド「 filefield() 」を利用することで、ローカルファイルのアップロードフォームを生成することが出来ます。メソッド filefield() のコードは、次のものでした。
print $q->filefield( -name => 'upload',
-default => 'default value',
-size => 50,
-maxlength => 80);
この Perl コードから得られる HTML コードは次のものでした。
<input type="file" name="upload" value="default" size="50" maxlength="80" />
しかしながら、当然の様に、ただこのコードだけでは、ファイルのアップロードを行うことは出来ません。ローカルファイルのアップロードを行うには、これに続けて、然るべき処理を書く必要があります。
基本的な処理 ( 変数の宣言 )
まず初めに、ファイルのアップロードに必要な各種変数を宣言します。
# param() でファイル名兼ファイルハンドル (?) を取得する。
my $filename = $q->param('upload');
# アップロード後のファイル名を相対パスで設定
my $output_file = "UPLOAD/test.file";
# 関数 read() のための変数を宣言
my ($bytesread, $buffer);
# 関数 read() で一度に読み込むバイト数を設定
my $numbytes = 1024;
変数の確認 $filename ( ファイル名兼ファイルハンドル (?) の取得 )
メソッド param() を利用してファイル名兼ファイルハンドル (?) を取得します。
my $filename = $q->param('upload');
現在は理解が浅い状態ですが、param() で取得したファイル名は、後で利用する関数 read() でファイルハンドルとして利用出来ます。
CGI.pm - perldoc.jp の例示では、メソッド「 upload() 」を利用して「 IO::Handle 」互換といわれるファイルアップロード用のハンドルを取得していますが、ここでは、param() を利用して進めます。
変数の確認 $output_file ( リモートのファイル名 )
リモートのファイル名の設定では、CGI プログラムと同じ階層にあるディレクトリ UPLOAD/ 直下に、ファイル名「 test.file 」でアップロードファイルを設置する様に指定しています。
my $output_file = "UPLOAD/test.file";
ファイル名「 test.file 」は、次の様にメソッド param() で取得したファイル名を利用することで、オリジナルのファイル名に置き換えることが出来ます。
# ファイル名を格納した変数をシステムパスに指定
my $output_file = "UPLOAD/$filename";
相対パスで指定しているシステムパスは、絶対パスに置き換えることも可能です。
変数の確認 $bytesread, $buffer, $numbytes ( 関数 read() のための設定 )
関数 read() を利用するための変数を設定します。
my ($bytesread, $buffer);
my $numbytes = 1024;
関数 read() は、これまで利用したことがありません。まずは書式を確認します。詳細は read - perldoc.jp を参照してください。
read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH
今回は、「 OFFSET 」を省いた 2 番目の書式を利用します。
関数 read() は、ファイルの終端を読み込んだ場合に、「 0 」を返すので、ループ構造の条件式として使えます。 スカラ変数「 $byteread 」は返された値を受けるための変数で、ループの条件式として利用します。
スカラ変数「 $buffer 」は、書式の「 SCALAR 」に当たります。SCALAR は、「 LENGTH 」で指定された分のデータを読み込んで、一時的に保持します。
数値「 1024 」が設定されたスカラ変数「 $numbytes 」は、書式の「 LENGTH 」に当たります。LENGTH は、一度に読み込むバイト数を指定しています。
変数「 $bytesread 」は、この LENGTH で指定されたバイト数の数値を受け取ります。つまり、1 ループ毎に 1024, 1024, 1024 ... と、データが続く限り 1024 ( 通常終端直前は半端なバイト数 ) を受け取り、ファイルの終端で 0 を受け取る訳です。
「 FILEHANDEL 」は、その名前の通り、ファイルハンドルを指定します。
通常 HTML フォームを利用したファイルアップロードでは、メソッド upload() で取得した IO::Handle 互換のファイルハンドルを指定する様ですが、今回は、ひとまずメソッド param() で取得したファイル名を指定します。
基本的な処理 ( ファイルハンドルオープン )
スカラ変数「 $output_file 」に指定した書き込み用のファイルに対し、書き出しモードでファイルハンドルをオープンします。ファイルハンドルの操作は (0x43) で確認しました。
open (OUTFILE, ">", "$output_file")
or die "Could't open $output_file for writing: $!";
3 引数の open 演算子を利用していることに注目します。3 引数の open 演算子は、Perl 5.6 以降から利用可能となった形式です。
後方互換により、同バージョン以降でも 2 引数の open 演算子は継続して利用可能となっていますが、2 引数の open 演算子では、セキュリティ上の懸念 ( 細工が施されたファイル名が効果を発揮する ) が発生するため、open 演算子を利用する場合は必ず 3 引数の open を利用します。3 引数の open は (0x44) で確認しました。
基本的な処理 ( ファイルの書き出し )
リモート領域へのファイルの書き出しは、while 制御構造と、関数 read() を利用します。
while ($bytesread = read($filename, $buffer, $numbytes)){
print OUTFILE $buffer;
}
close OUTFILE;
関数 read() で、$filename ( FILEHANDLE ) から、$numbytes ( LENGTH ) の分だけ読み込んだファイルの内容を、$buffer ( SCALAR )に格納し、書き出しモードのファイルハンドル OUTFILE に出力します。
ファイルの終端を読み込むと、関数 read() が「 0 」を返すので、while ループが終了します。その後ファイルハンドルをクローズします。
0x109 -> 0x10a へ
今回の Perl コードは Cgi upload - perlmeme.org のコードを参考にしています。
このページの冒頭には次の 1 文があります。
If you have never done any perl CGI programming before, we suggest you first look at the CGI Tutorial and CGI Forms Tutorial.
「 もしあなたが、何かしらの Perl CGI プログラムをやったことがないなら, 先に CGI と CGI フォームのチュートリアルを確認することをお勧めする。」といった内容です。
確かに、CGI.pm - perldoc.jp の前半部を経ていなければ、今頃僕は悶絶していた様に思います。
次回は、ファイルをアップロードするプログラムの動作を確認します。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)