アップロードファイルのバリデーションルール

CakePHP 2.2や2.3になってファイルアップロードに対するルールがコアバリデーションに追加されているようで、まとめてみました。

コアバリデーション

関連しそうなルールは以下の4つのようです。
fileSize - ファイルサイズについて
mimeType - MIMEタイプについて
uploadError - ファイルアップロードのエラー有無について
extension - 拡張子について

ファイルアップロードフォームから受け取るデータ配列

簡単なフォームの例

<?php 
echo $this->Form->create( 'File', array( 'type'=>'> file', 'enctype' => 'multipart/form-data', 'url'=>'/upload/'));
    echo $this->Form->input( 'image', array( 'type' => 'file'));
    echo $this->Form->submit( __('Upload'));
echo $this->Form->end(); 
?>

上記のフォームから受け取るこんな感じだと思います。

    [File] => Array
        (
            [image] => Array
                (
                    [name] => 5231ddd0ccdbf_thumb.jpg
                    [type] => image/jpeg
                    [tmp_name] => /var/tmp/phpCN8Bo8
                    [error] => 0
                    [size] => 4613
                )

        )

バリデーションルールを設定

配列がネストしているのでバリデーションルールもネストする必要があるのかなと思ったのですが、Cake側でやってくれるようで、そのまま定義すればいいようです。
ポイントは、「uploadError」ルールを先頭にもってくることでしょうか? ファイル未選択で空の場合にはここではじかないと、その他のルールを実行しようとしてエラーが発生してしまいます。

// モデル:File.php
public $validate = array(
    'image' => array(

        // ルール:uploadError => errorを検証 (2.2 以降)
        'upload-file' => array( 
            'rule' => array( 'uploadError'),
            'message' => array( 'Error uploading file')
        ),

        // ルール:extension => pathinfoを使用して拡張子を検証
        'extension' => array(
            'rule' => array( 'extension', array( 
                'jpg', 'jpeg', 'png', 'gif')  // 拡張子を配列で定義
            ),
            'message' => array( 'file extension error')
        ),

        // ルール:mimeType => 
        // finfo_file(もしくは、mime_content_type)でファイルのmimeを検証 (2.2 以降)
        // 2.5 以降 - MIMEタイプを正規表現(文字列)で設定可能に
        'mimetype' => array( 
            'rule' => array( 'mimeType', array( 
                'image/jpeg', 'image/png', 'image/gif')  // MIMEタイプを配列で定義
            ),
            'message' => array( 'MIME type error')
        ),

        // ルール:fileSize => filesizeでファイルサイズを検証(2GBまで)  (2.3 以降)
        'size' => array(
            'maxFileSize' => array( 
                'rule' => array( 'fileSize', '<=', '10MB'),  // 10M以下
                'message' => array( 'file size error')
            ),
            'minFileSize' => array( 
                'rule' => array( 'fileSize', '>',  0),    // 0バイトより大
                'message' => array( 'file size error')
            ),
        ),
    ),
);

ファイル名の長さを検証するケースはあまり無いと思いますが、自作する必要があるようですね。(存在してたらすいません)

処理の流れの注意点

通常の流れは、「ファイルアップロード」→「バリデーション」→「ファイル移動(move_uploaded_file)」→「ファイル情報save」のような感じになると思います。

mimeTypeのバリデーション処理では、tmp_nameにあるファイルからmime情報を取得してバリデーションを行うため、save時は、'validate' => falseを付与して、バリデーション処理をスキップさせて下さい。(コントローラ内でバリデーション処理を呼び出す)
そうしないと既に移動されて存在しないファイルに対してバリデーション処理をおこなうためエラー("Can not determine the mimetype.")となってしまいます。

// バリデーション
$this->File->set( $this->request->data );
if ($this->File->validates( array( 'fieldList' => array( 'image')))) {
    // ファイル移動
    if( move_uploaded_file( $this->request->data['File']['image']['tmp_name'], IMAGES . 「ファイルパス」) ){
        // save
        if( $this->File->save( $this->request->data, array( 'validate' => false)) ) {
        } else {
            // saveエラーの場合
        }
    } else {
        // ファイル移動エラーの場合
    }
} else {
    // バリデーションNGの場合
}

(ファイル情報saveしてからファイル移動(move_uploaded_file)であれば、問題ないと思いますが。)

Validationユーティリティ:/lib/Cake/Utility/Validation.php
Models > Data Validation
  • このエントリーをはてなブックマークに追加

関連記事

ログローテーション

CakePHP 2.xではbootstrap.php内にあらかじめアプリケーションログの設定が書かれています。2.xで日付ごとにログファイルが切り替わるよう設定してみました。 日ごとにログを切り替え

数値系バリデーション

CakePHP 2になっていくつか数値用バリデーションルールが追加されています。 数値用 (コア)バリデーション decimal - 十進数であること numeric - 数値であること

selectボックスを実装

今まで、selectボックスのgroupを作成するのにSet::Combineを使用していましたが、意外と簡単にできることに気付いてしまったので、ご紹介。(自分だけ知らなかったことに気付いた と言った

recursive設定によるfind()性能改善

CakePHPでは、モデルにアソシエーションを設定している場合、recursive(=>joinする階層)はデフォルトで0に設定されています。「recursiveゼロ」の意味するところとは、「1跨ぎま

hasOne アソシエーション

hasOneアソシエーションはテーブル間で1つのレコードに対して他のテーブルに紐付くレコードが1つの場合にjoinする場合に使用します。 CakePHPのドキュメントにならってUserモデルとP

FullCalendarを使用してカレンダーアプリケーション

カレンダーアプリケーションを作成するため、カレンダー表示できるプラグインを探索して出会ったFullcalendarを試してみました。シンプルに使用できる上に、オプションがかなり豊富です。ダウンロード

CakePHP 2.x インストール

現在まで私が商用・非商用にリリースしているCakePHPアプリケーションは全て1.3.xベースで作成しています。 まだまだロードマップ的には大丈夫そうですが、お客さん向けに納品しているアプリケーショ

Syslogログエンジン

2.4から「Syslog」ログクラスが追加され、簡単にSyslogを使用できるようになりました。 CakePHP側の設定はbootstrap.php内のCakeLogコンフィグのengineを'Sy

SQLクエリーをログに出力する

SQLのクエリーをデバッグするには、Debug Kitを使用すればできますが、デバッグログと一緒に出したいのでやり方を調査してみました。 別々のログやビューでみるのもいいですが、秒単位で実行される処

ログインに追加の条件を付与する「scope」

ユーザ登録では、仮登録処理(status=1)から送付したメール内のリンクをクリックしてもらい本登録(status=0)を行ってもらう実装をしました。仮登録の状態ではログインできないように実装するには

Comment

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

    PAGE TOP ↑