CakePHPのPluginであるUpload_Packの困った動作

バグではないのでしょうが、ちょっと困った動作をしました。

例えば「1-1.jpg」や「2 2.jpg」といったファイル名のファイルをアップロードした場合、データベースのファイル名フィールドにはそのまま「1-1.jpg」「2 2.jpg」と記録されます。

ところが、Upload_Packがテンポラリフォルダから$actsAsで指定したPathに移動する際、リネームしてしまい「1_1.jpg」や「2_2.jpg」になります。
ハイフン、スペース、ドットなどの特殊文字がエスケープされ、アンダーバーに変換されてしまうのです。

これはURLにふさわしいファイル名にするようCakePHP内のInflector::slugをファイル名に対して実行しているからです。

本来であれば特殊文字などURLにふさわしくない文字をエスケープしてくれる関数なのですが、データベース内のファイル名とリネーム後のファイル名が変わってしまうため、表示させようとしてデータベースからファイル名をひっぱってきても、ファイルが存在しないという自体に陥ってしまいます。

解決法その1 – Upload_Pack内のInflector::slugを無効にする

[php title=’upload_pack/Model/Behavior/UploadBehavior.php’] private function _prepareToWriteFiles(&$model, $field) {
$this->toWrite[$field] = $model->data[$model->name][$field];
// make filename URL friendly by using Cake’s Inflector
$this->toWrite[$field][‘name’] =
Inflector::slug(substr($this->toWrite[$field][‘name’], 0, strrpos($this->toWrite[$field][‘name’], ‘.’))). // filename
substr($this->toWrite[$field][‘name’], strrpos($this->toWrite[$field][‘name’], ‘.’)); // extension
}
//↓↓↓↓↓↓該当部分をコメントアウトする。
private function _prepareToWriteFiles(&$model, $field) {
$this->toWrite[$field] = $model->data[$model->name][$field];
// make filename URL friendly by using Cake’s Inflector
// $this->toWrite[$field][‘name’] =
// Inflector::slug(substr($this->toWrite[$field][‘name’], 0, strrpos($this->toWrite[$field][‘name’], ‘.’))). // filename
// substr($this->toWrite[$field][‘name’], strrpos($this->toWrite[$field][‘name’], ‘.’)); // extension
}[/php]ただし、ファイル名内の特殊文字は残ってしまうため、最善の方法とは言えません。

解決法その2 – saveAll前にリクエストデータを書き換える

データベースの記録&upload_packによるリネームの前にファイル名をエスケープさせる作戦です。
[php]$oriName = $_FILES[‘data’][‘name’][Model][‘img’];
$_FILES[‘data’][‘name’][‘Post’][‘photo’.$ii] = Inflector::slug(substr($oriName, 0, strrpos($oriName, ‘.’))). //filename
substr($oriName, strrpos($oriName, ‘.’)); //extension[/php]
こちらの方法がオススメです。

スポンサーリンク