修正版を掲載しました.
本エントリの内容は,Plack-0.9031におけるものです.
本エントリの投稿時点で「**DEVELOPER RELEASE**」としてPlack-0.99_05が公開されてれおり,「0.9031」から内容が大きく変わっています.
@miyagawa
ご指摘ありがとうございます.
はじめに
YAPC::Asia 2009でのキーワードの1つとなったPSGI/Plackについて,ようやく少しかじり出しました.
まずは,Plack Advent Calendarを一日かけて一気読み,ほんの表面的だけですが,ようやく概要くらいはつかめた気がします.
前置きはさておき,以下,Plackにおけるファイルアップロード処理のための,ほんのざっと下調べしたメモを備忘録として残しておきます.
こんな感じのフォームの場合
サンプルとして次のようなフォームからアップロードを行うことを考えてみます.
<form action="" method="post" enctype="multipart/form-data"> ファイル 1-1 <input type="file" name="file1" value="" /> ファイル 1-2 <input type="file" name="file1" value="" /> ファイル 2 <input type="file" name="file2" value="" /> <input type="submit" name="submit" value="アップロード!" /> </form>
Plack::Request::Uploadオブジェクトを取得する
アップロードオブジェクトの集合体(?)
Plack::Requestオブジェクトのuploadsメソッドを呼ぶことで,ファイルアップロードの要素の集合を,ハッシュリファレンスとして取得できます.
# $req: Plack::Request my $uploads = $req->uploads;
データ構成
$uploadsがどんな構成なのかを,ダンプして確認してみます.スペースの都合上,$VAR1 =な部分は削ってます.
use Data::Dumper; print Dumper $uploads;
{
'file2' => bless( {
'headers' => bless( {
'content-disposition' => 'form-data; name="file2"; filename="9a8ba767.jpg"',
'content-type' => 'image/jpeg'
}, 'HTTP::Headers' ),
'filename' => '9a8ba767.jpg',
'tempname' => '/tmp/zKMx5lPeQm',
'size' => 102723
}, 'Plack::Request::Upload' ),
'file1' => [
bless( {
'headers' => bless( {
'content-disposition' => 'form-data; name="file1"; filename="6ac3d070.jpg"',
'content-type' => 'image/jpeg'
}, 'HTTP::Headers' ),
'filename' => '6ac3d070.jpg',
'tempname' => '/tmp/MsOfRtTGPe',
'size' => 59307
}, 'Plack::Request::Upload' ),
bless( {
'headers' => bless( {
'content-disposition' => 'form-data; name="file1"; filename="7a98edb3.jpg"',
'content-type' => 'image/jpeg'
}, 'HTTP::Headers' ),
'filename' => '7a98edb3.jpg',
'tempname' => '/tmp/iSiVfM9ghl',
'size' => 301283
}, 'Plack::Request::Upload' )
]
};特定のフィールドの要素を取得する
ということで,フィールド名をハッシュリファレンス$uploadsのキーとして指定してやればOKです.
my $up1 = $uploads->{file1}; my $up2 = $uploads->{file2};
ただし,冒頭のフォームのように,1つのフィールドに複数の要素が存在する場合,リストリファレンスが得られることに注意です.この場合,リストの要素がそれぞれPlack::Request::Uploadオブジェクトとなっています.
print Dumper ref $up1; print Dumper ref $up2;
$VAR1 = 'ARRAY'; $VAR1 = 'Plack::Request::Upload';
Plack::Request::Uploadオブジェクトのメソッド
CPANのPlack::Request::Uploadモジュールのページには,現在4つのメソッドのみ書かれていますが,同モジュールの基となっている(のかな?不勉強です><)Catalyst::Request::Uploadモジュール同じ感じで使えるみたいですね.
print Dumper $up1->[0]->tempname; print Dumper $up1->[0]->type; print Dumper $up1->[0]->headers; print Dumper $up1->[0]->fh;
$VAR1 = '/tmp/O3ECOY_iD8';
$VAR1 = 'image/jpeg';
$VAR1 = bless( {
'content-disposition' => 'form-data; name="file1"; filename="6ac3d070.jpg"',
'content-type' => 'image/jpeg'
}, 'HTTP::Headers' );
$VAR1 = \*{'Plack::Request::Upload::$fh'};参考
詳しくはこのあたりを.
- Plack::Request::Upload – search.cpan.org
- Plack::Request – search.cpan.org
- Catalyst::Request::Upload – search.cpan.org
- HTTP::Headers – search.cpan.org
おわりに
Plackの部分でほとんどやってくれてますので,ファイルのアップロード処理も簡単に準備できますね.
あとはSWFUploadとの連携もしなければ...あ,2.5.0 Beta 2に上がってるじゃん.

> ただし,冒頭のフォームのように,1つのフィールドに複数の要素が存在する場合,リストリファレンスが得られることに注意です
Plack 0.99 以降ではそのようになりません。Hash::MultiValue オブジェクトになるので、ハッシュとして扱えば最後の要素のみ、複数取得する場合は ->get_all を使用します。
Upload オブジェクトのメソッドも一部かわっているので CPAN にあがっている 0.99 以降を参照してください。
http://search.cpan.org/~miyagawa/Plack-0.99_05/
@miyagawa
ご指摘ありがとうございます.
Hash::MultiValueについて不勉強なので,まずそれを把握した上で,0.99系の確認を行いたいと思います.
ひとまずの対策として,冒頭に,バージョン間に違いがあることについて追記しましました.
本エントリの修正版を掲載しました.
http://blog.iwa-ya.net/2010/02/12/143801
eckwecmph, http://www.schoolfundstore.com/ Generic Ambien, gyoPELY.