複数ファイルをアップロードできるjQueryのプラグイン「Uploadify」をCakePHPで使ってみる
2015/09/10
前回に続き、ファイルをまとめてアップロードする jQuery のプラグイン「Uploadify」の使い方。
今回はCakePHPでの設置の方法を晒してみたいと思います。
「Uploadify」の設置
【設置構成】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[www] ├[js] ←ライブラリ用フォルダ │ └[uploadify] ←本体 └[media] ←アップロード用フォルダ [cakephp] └[app] ├[controller] │ └media_controller.php ├[model] │ └medium.php └[view] └[media] └upform.ctp ←アップロードフォーム |
上記構成で説明します。
前回のアップロードフォルダは「uploads」でしたが、今回は media とします。
ちなみに、 media は medium の複数形ですので、覚えておくと良いことがあるかも。
DBへの書き込みも行うので、適当にこのようなSQLでテーブル作成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CREATE TABLE IF NOT EXISTS `media` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `created` DATETIME NOT NULL, -- 登録日時 `modified` DATETIME NOT NULL, -- 編集日時 `pic_large` VARCHAR(255) default NULL, -- 等倍画像 `pic_middle` VARCHAR(255) default NULL, -- 中サイズ用画像 `pic_small` VARCHAR(255) default NULL, -- 小サイズ画像 `pic_mobile` VARCHAR(255) default NULL, -- 携帯用画像 `alt` VARCHAR(255) default NULL, -- alt `title` VARCHAR(255) default NULL, -- 代替テキスト `caption` VARCHAR(255) default NULL, -- キャプション `description` VARCHAR(255) default NULL, -- 説明 `width` INT default NULL, -- 幅px `height` INT default NULL, -- 縦px `path` VARCHAR(255) default NULL, -- 絶対パス PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
view
アップロードフォーム(/app/views/upform.ctp)
レイアウトかヘッダ辺りで jQuery と uploadify を読み込んで下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php echo '<p class="upform">SELECT FILES ボタンを押し、ファイルを選択して下さい。<br />複数の画像を選択することも可能です。</p>'; echo $form->create('Medium', aa('type','post', 'action','upload')); echo '<div id="queue" style="background-color: #505050; height: 200px; margin-bottom: 10px; padding:10px; overflow: auto; width: 400px;"></div>'; echo $form->file('Medium.upload_file', aa('id','file_upload')); echo $form->end(null); $timestamp = time(); ?> <script type="text/javascript"> <!-- $(document).ready(function() { $('#file_upload').uploadify({ 'formData' : { 'timestamp' : '<?php echo $timestamp;?>', 'token' : '<?php echo md5('unique_salt' . $timestamp);?>' }, 'debug' : false, 'uploader' : '/media/upload', 'swf' : '/js/uploadify/uploadify.swf', 'auto' : true, 'queueID' : 'queue', 'fileTypeDesc' : 'Image Files', 'fileTypeExts' : '*.gif; *.jpg; *.png', }); }); --> </script> |
controller
アップロードフォーム用アクション : upform
単に表示するだけです。
1 2 3 4 5 |
function upform() { // htmlタイトル $this->set('title_for_layout', 'メディアアップロード'); } |
アップロード用アクション
uploadify.php を元に作成しています。
途中にあるパスはapp.php で以下のように設定しています。
PIC_PATH_MEDIA
define('PIC_PATH_MEDIA', WWW_ROOT . 'media/img/'); // WEBルートから
PIC_DIR_PATH_MEDIA
define('PIC_DIR_PATH_MEDIA', "/" . "media/img/"); // 絶対パス
PIC_WIDTH_MIDDLE、
PIC_WIDTH_SMALL、
PIC_WIDTH_MOBILE には、保存する画像のピクセルサイズを指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
function upload() { // レイアウトは使用しない。 $this->layout = null; $this->autoLayout = false; // アップロード情報がないなら終了 if ( empty($_FILES) ) { exit(); } // 画像をアップするパス(WWW_ROOTからのパス) $path = $path = PIC_PATH_MEDIA; $verifyToken = md5('unique_salt' . $_POST['timestamp']); $microtime = (microtime()*1000000); if ( !empty($_FILES) && $_POST['token'] == $verifyToken ) { // $name = $_FILES['Filedata']['name']; $tempFile = $_FILES['Filedata']['tmp_name']; // Validate the file type $fileTypes = array('jpg','jpeg','gif','png'); // File extensions $fileParts = pathinfo($_FILES['Filedata']['name']); // ファイル名がアルファベットのみかをチェック if ( preg_match("/^([a-zA-Z0-9\.\-\_])*$/u", $name) == false ) { $saveFileName = date("Ymd_His", time()); // 日時で } else { if ( preg_match("/\.jpg$/ui", $name) == true ) { $ret = explode('.jpg', $name); } elseif ( preg_match("/\.gif$/ui", $name) == true ) { $ret = explode('.gif', $name); } elseif ( preg_match("/\.png$/ui", $name) == true ) { $ret = explode('.png', $name); } $saveFileName = $ret[0]; // 拡張子を除いたそのまま } // フォルダ内を検索し、同名ファイルがあれば、保存ファイル名をタイムスタンプとする if ( is_file(PIC_PATH_MEDIA . $name) == true ) { $saveFileName = date("Ymd_His", time()); // 日時で } // マイクロ秒をファイル名に付加 $saveFileName = $saveFileName . $microtime; if ( in_array($fileParts['extension'],$fileTypes) ) { // アップロード処理(戻り値:ファイル名) $pic_large = $this->CompImageUpload->copyUploadFilenameNotChange($name, $tempFile, $path, $saveFileName, 1); // 縦横そのまま $pic_middle = $this->CompImageUpload->sizeChangeUploadFilenameNotChange($name, $tempFile, $path, $saveFileName, PIC_WIDTH_MIDDLE, 1, "middle"); $pic_small = $this->CompImageUpload->sizeChangeUploadFilenameNotChange($name, $tempFile, $path, $saveFileName, PIC_WIDTH_SMALL, 1, "small"); $pic_mobile = $this->CompImageUpload->sizeChangeUploadFilenameNotChange($name, $tempFile, $path, $saveFileName, PIC_WIDTH_MOBILE, 1, "mobile"); //echo '1'; if ( ($pic_large === false) || ($pic_middle === false) || ($pic_small === false) || ($pic_mobile === false) ) { $error_message = '画像ファイルが正しくないか、ファイルサイズがオーバーしています。'; $this->makeErrorMessage($error_message); $this->list(); $this->render('list'); return; } // 拡張子を除いたファイル名作成 if ( preg_match("/\.jpg$/ui", $pic_large) == true ) { $fname = explode('.jpg', $pic_large); } elseif ( preg_match("/\.gif$/ui", $pic_large) == true ) { $fname = explode('.gif', $pic_large); } elseif ( preg_match("/\.png$/ui", $pic_large) == true ) { $fname = explode('.png', $pic_large); } //------------------------------------------------------------ // media テーブルここから //------------------------------------------------------------ // トランザクション開始 $this->Medium->begin(); // ID初期化 $this->Medium->id = NULL; // 登録データ成形 $save_media_datas = array( 'Medium' => array( 'pic_large' => $pic_large, 'pic_middle' => $pic_middle, 'pic_small' => $pic_small, 'pic_mobile' => $pic_mobile, 'alt' => $fname[0], 'title' => null, 'caption' => null, 'description' => null, 'path' => PIC_DIR_PATH_MEDIA, ) ); // DB登録実行 if ( !$this->Medium->save($save_media_datas, 0) ) { $this->Medium->rollback(); // RollBack if ( $this->Medium->getDbo()->error !== null ) { $message = "メディア登録エラー\n"; $message .= "[SQL ErrorCode] " . $this->Medium->getDbo()->error . "\n"; } // エラーログ作成 $this->_log('メディア登録エラー', __LINE__); // 失敗したらフォームに戻る $this->list(); $this->render('list'); return; } //------------------------------------------------------------ // media テーブルここまで //------------------------------------------------------------ // 確定(Commit) $this->Medium->commit(); } else { echo 'Invalid file type.'; } } } |
CakePHPなので、「$_POST」とか「$_FILES」を「$this->data」で受けたかったのですが、うまく取得できなかったので、「$_POST」「$_FILES」形式で取得しています。
アップロードの処理は独自で作成したコンポーネントを使用しています。
やってることは、tmpデータを指定されたファイル名でサイズそのままと、サイズを変えてコピーするだけです。
戻り値はそれぞれ、ファイルネームを返しています。
要望があればまたそちらも公開したいと思います。
戻ってきたら、DBにインサートしているだけ。その辺りは問題ないと思います。
model
Medium.php
最後にモデル。
特にアップロードに関して処理していませんので、以下のように。
1 2 3 4 5 6 |
<?php class Medium extends AppModel { var $name = 'Medium'; } ?> |
と、早足ですが、とりあえずはこれで toogie の環境(ウェブサーバと Windows7 に作ったローカル環境)で走っています。
動かないって方は、まずは通常の PHP で動くかどうかを試してから、CakePHP にとりかかるのがよろしいかと思います。
ちなみにこの CakePHP 版を作るのに toogie は2日掛けてしまいました(苦笑
何かのお役に立てれば幸いです。
[tgAmazonItemLookup asin="4150309930" related="1"]