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

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
  • このエントリーをはてなブックマークに追加

関連記事

ユーザ登録(仮登録・メール・本登録)

以前1.3版で投稿した「ユーザ登録」処理の2.x版を作成しました。フローは同じで以下のようにします。 1. メールアドレス・パスワードでユーザ登録 2. この時点では仮登録として、本登録用のU

Blowfishを使用してハッシュ化する

使用方法 Blowfishを採用してハッシュ化を行う場合、Securityクラスのhashメソッドを呼び出します。第2引数に'blowfish'を指定し、第3引数を指定しないもしくはfalseにしま

selectボックスを実装

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

多言語サイト向けに翻訳ファイルを使って翻訳を行う

CakePHPには、翻訳をビヘイビアを使用する方法と翻訳ファイルを使用する方法の2つがあるそうです。(他にもあるのかな?) 今回は、翻訳ファイルを使用して言語の切り替えを行い、その言語設定をCook

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

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

パス定数と変更方法やURLの取得

CakePHPは基本的にはディレクトリそのまま配置することで構築が可能ではありますが、設定パスを変更することでセキュリティに考慮した構成にすることや運用性をもたせたものにすることが可能になります。

ログローテーション

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

Jsヘルパーを使用してAjax更新

更新処理でページ遷移を伴う場合、ページ全体をレスポンスするのに対して、Ajax処理ではページの一部のレスポンスが可能となるためサーバからの通信量を抑えることが可能となります。デモ head

hasOne アソシエーション

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

バリデーションエラーメッセージの取得

CakePHP 2.xになってバリデーションエラー時に返却されるメッセージのデータ形式が変更になったようです。1.3系では、ひとつのフィールドに対して返却されるメッセージは一つのルールのみですが、2.

Comment

Message

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

*

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

    PAGE TOP ↑