CakePHPでファイルアップロード処理を作る

CakePHPでファイルアップロードフォームを作る機会がありましたので、記録しておきます。
ちなみにCakePHPのバージョンは1.2です。

まずはフォームを表示するビュークラスのテンプレートファイル記述から。
アップロードされたファイルを UploadsController クラスの upload メソッドで処理する想定です。

<?php
	$options = array(
		'action'=>'upload',
		'type'=>'file'
	);
	echo $form->create('Upload', $options);
?>
	<dl>
		<dt>ファイル:</dt>
		<dd><?php echo $form->file('file_name') ?>
		<?php echo $form->error('file_name') ?></dd>
	</dl>
	<?php echo $form->submit('送信'); ?>
<?php echo $form->end(); ?>

実際は付随する情報をいろいろ入力すると思いますが、分かりやすくするため最小限の構成にしています。
Formヘルパーのcreate()メソッドに渡すオプションで「”type”=>”file”」を指定すると、ファイルのアップロードに対応したHTMLタグが出力されます。(2010-03-29 加筆修正)
formヘルパーの個々のメソッドについてはここでは解説しません。

次にこのフォームからの送信情報を受け取るコントローラークラスの記述です。
以下のような条件を想定しています。

  • アップロードされたファイル名は uploads テーブルの file_name カラムに保存される
  • アップロードされたファイルの置き場所は設定ファイルに定義済み
  • マルチバイト文字が含まれるファイル名は禁止(エラーメッセージを出力)
  • ファイル名の重複を防ぐ処理を入れる

今回は省略しますが、さらに安全を期するならファイル形式のチェック機能なども必要かと。

// コントローラー定義
class UploadsController extends AppController {

	var $name = 'Uploads';
	var $uses = array('Upload');

/* 他のメンバー変数 */

/**
 * ファイルアップロードメソッド
 */
	public function upload(){
		if (!empty($this->data)) {
			if( is_uploaded_file($this->data['Upload']['file_name']['tmp_name']) ){
				if( strlen($this->data['Upload']['file_name']['name']) == mb_strlen($this->data['Upload']['file_name']['name']) ){
					//アップロードするファイルの場所
					$uploaddir = Configure::read('upload.path');
					$uploadfile = $uploaddir.DS.basename($this->data['Upload']['file_name']['name']);
					// 同じ名前のファイルがすでに存在すれば、別名に変える
					$info = pathinfo($uploadfile);
					$i = 1;
					while( file_exists($uploadfile) ){
						$i++;
						$file_name = basename($info['basename'],'.'.$info['extension']).
							'_'.$i.'.'.$info['extension'];
						$uploadfile = $info['dirname'].DS.$file_name;
						$this->log('アップロードファイル名を再作成:'.$uploadfile, LOG_DEBUG);
						$this->data['Upload']['file_name']['name'] = $file_name;
					}
					//画像をテンポラリーの場所から、正式な置き場所へ移動
					if (move_uploaded_file($this->data['Upload']['file_name']['tmp_name'], $uploadfile)){
						chmod($uploadfile, 0666);
						$this->Upload->create();
						// DBにレコード登録
						$this->data['Upload']['file_name'] = $this->params['data']['Upload']['file_name']['name'];
						if( $this->Upload->save($this->data) ){
							//成功
							$this->Session->setFlash("ファイルのアップロードに成功しました。");
						} else {
							//失敗
							$this->Session->setFlash("データベースの登録に失敗しました。");
						}
					} else {
						//失敗
						$this->Session->setFlash("ファイルのアップロードに失敗しました。");
					}
				}else{
					$this->Upload->invalidate("file_name","ファイル名に全角文字は使用できません。");
				}
			} else {
				$this->Upload->invalidate("file_name","ファイルをアップロードしてください。");
			}
		}
	}

/* 他のメソッド */

}

とりあえずこれで最小限の構成でしょうか。
本当は付随する情報も含めた保存データを処理するために、モデルクラスにも独自メソッドを用意したりしていますが、そこは皆さんの創意工夫でお願いします・・・。

2011-10-13 追記:
読者の方からご指摘がありまして、ソースコードを一部修正いたしました。

コントローラ定義の35行目

// /*誤*/$this->data['file_name'] => $data[$this->name]['file_name']['name'];
/*正*/ $this->data['Upload']['file_name'] = $this->params['data']['Upload']['file_name']['name'];

こんな昔の拙い記事を(しかも自分は現在CakeはおろかPHPもろくに触っていなかったりしますが)参考にして何かを創り出そうと頑張っている人がいると思うと励みになります。
ありがとうございました!

This entry was posted in Webプログラミング and tagged . Bookmark the permalink.

One Response to CakePHPでファイルアップロード処理を作る

  1. Pingback: cakePHP2.0 画像のアップロード処理(簡易版) | Web情報サイト「Web見」

コメントを残す

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

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>