
複数ファイルをアップロードできる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でテーブル作成。
[sql]
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;
[/sql]
view
アップロードフォーム(/app/views/upform.ctp)
レイアウトかヘッダ辺りで jQuery と uploadify を読み込んで下さい。
[php]
<?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>
[/php]
controller
アップロードフォーム用アクション : upform
単に表示するだけです。
[php]
function upform()
{
// htmlタイトル
$this->set('title_for_layout', 'メディアアップロード');
}
[/php]
アップロード用アクション
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 には、保存する画像のピクセルサイズを指定しています。
[php]
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.';
}
}
}
[/php]
CakePHPなので、「$_POST」とか「$_FILES」を「$this->data」で受けたかったのですが、うまく取得できなかったので、「$_POST」「$_FILES」形式で取得しています。
アップロードの処理は独自で作成したコンポーネントを使用しています。
やってることは、tmpデータを指定されたファイル名でサイズそのままと、サイズを変えてコピーするだけです。
戻り値はそれぞれ、ファイルネームを返しています。
要望があればまたそちらも公開したいと思います。
戻ってきたら、DBにインサートしているだけ。その辺りは問題ないと思います。
model
Medium.php
最後にモデル。
特にアップロードに関して処理していませんので、以下のように。
[php]
<?php
class Medium extends AppModel
{
var $name = 'Medium';
}
?>
[/php]
と、早足ですが、とりあえずはこれで toogie の環境(ウェブサーバと Windows7 に作ったローカル環境)で走っています。
動かないって方は、まずは通常の PHP で動くかどうかを試してから、CakePHP にとりかかるのがよろしいかと思います。
ちなみにこの CakePHP 版を作るのに toogie は2日掛けてしまいました(苦笑
何かのお役に立てれば幸いです。
[tgAmazonItemLookup asin="4150309930" related="1"]