2010-02-11 20:55 追記
本エントリの内容は,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の部分でほとんどやってくれてますので,ファイルのアップロード処理も簡単に準備できますね.

あとはSWFUploadとの連携もしなければ...あ,2.5.0 Beta 2に上がってるじゃん.

こちらもあわせてどうぞ

3 Responses to “[plack][perl] Plackにおけるファイルアップロード処理の準備メモ”

  1. > ただし,冒頭のフォームのように,1つのフィールドに複数の要素が存在する場合,リストリファレンスが得られることに注意です
    Plack 0.99 以降ではそのようになりません。Hash::MultiValue オブジェクトになるので、ハッシュとして扱えば最後の要素のみ、複数取得する場合は ->get_all を使用します。

    Upload オブジェクトのメソッドも一部かわっているので CPAN にあがっている 0.99 以降を参照してください。
    http://search.cpan.org/~miyagawa/Plack-0.99_05/

  2. issm より:

    @miyagawa

    ご指摘ありがとうございます.
    Hash::MultiValueについて不勉強なので,まずそれを把握した上で,0.99系の確認を行いたいと思います.

    ひとまずの対策として,冒頭に,バージョン間に違いがあることについて追記しましました.

  3. issm より:

    本エントリの修正版を掲載しました.

    http://blog.iwa-ya.net/2010/02/12/143801

Leave a Reply

直近のつぶやきを読み込みちゅう...