blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_2

Perl 「 モジュール 」 CGI.pm フォーム ファイルアップロードの基本処理 (0x109)

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)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲