エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP3でファイルのアップロード処理を自作・解説付き・その1

      2017/04/08

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

 
CakePHPでは、下記の GitHubに公開されているファイルアップロードプラグインがよく利用されているそうです。
 
https://github.com/josegonzalez/cakephp-upload/blob/master/README.md#requirements
 
ですが、このプラグインでは、アップロードしたファイルのサムネイルを作成するのですが、その際に GDライブラリか、Imagickライブラリを使います。
そのため、GD、Imagickのいずれかが利用でいないとこのプラグインを利用できないのですが、レンタルサーバの場合は、ライブラリを自由にインストールできない場合もあろうかと考え、まずは、アップロード処理を自作してみることにしました。
 
 

画像アップロードを行う画面の前提

 
一般的な CMSを想定し、ニュース登録の画面を作成します。
その中に、画像の登録を行う項目があることを想定しています。
 
 
テーブルは下記を想定し、必要なプログラムは、bake allで生成しているものとして話を始めます。
 

 
 
フォームの画面は下記のようなイメージです。
CakePHP3でファイルのアップロード処理を自作・解説付き・その1
 
 

テンプレートファイルの変更

 
ファイルのアップロードをするには、まず、formタグを修正する必要があります。
 
CakePHP3の Formヘルパーの使い方は「CakePHP3のForm Helperの使い方のまとめ」で解説をしていますので、詳しくはそちらを参照してください。
 
 

add.ctp、edit.ctpを変更

 
アップロードする画像を入力する画面となるテンプレートの変更を行います。
対象ファイルは、以下の 2ファイルです。
 
/src/template/news/add.ctp
/src/template/news/edit.ctp
 
修正箇所は以下の通りです。
Formタグでファイルのアップロードを扱えるようにします。
 

 
 
inputタグのタイプを fileに変更します。
 

 
 

アップロードされる画像の確認

 
入力フォームを修正しただけで、画像をアップロードすることはできます。
 
実際にアップロードしたファイルを、コントローラー側では下記の様に記述することで受け取っていることを確認することができます。
 
/src/controller/NewsController.php
 

 
これにより、ログファイルには下記の情報が出力されます。
ログファイルへの出力する方法の解説は「   」を参照してください。
 

 
入力フォームに追加したファイルの入力項目「file_name」から送信された値が取得できていることが確認できます。
 
ただ、この状態では、送信された画像ファイルは、「tmp_name」の値にあるように「C:\xampp\tmp\php37DC.tmp」という一時ファイルとして生成されますが、その後の処理でそのファイルも削除されてしまいます。
 
そのため、この一時ファイルを希望する場所に移すための処理を記述します。
加えて、ファイルがアップロードされていない場合や、ファイルサイズが大きい場合、想定しているファイル種類でない場合などのチェックも行います。
 
 


 

コントローラーの変更

 
ファイルアップロードの処理を作成するにあたって、必要になる処理をコントローラーに追記します。
 
対象となるコントローラーファイルは、下記になります。
/src/controller/NewsController.php
 
 

必要なクラスをロードする処理

 
ファイルアップロードの処理に必要となるクラスをロードする処理、下記の内容を追記します。
 

 
Folder、Fileクラスに関しては下記が参考になります。
 https://book.cakephp.org/3.0/ja/core-libraries/file-folder.html
 
「RuntimeException」クラスに関しては下記が参考になります。
 http://waterada.ldblog.jp/archives/20000008.html
 
 

ファイルアップロードの処理の追記

 
下記の 4~12行目を追加します。
「add()」「edit()」アクションに追加します。
 

 
5行目で、アップロードするファイルを保存するフォルダのパスを指定します。
6行目で、アップロードするファイルの容量の最大値を指定します。
 
そして、8行目で自作のファイルアップロード関数「file_upload()」に、ファイルの入力項目の値「$this->request->data['file_name']」と、5行目、6行目で指定した値を引数として渡して、関数を実行します。
(今回は、同一コントローラー内の関数としてアップロード処理を作っていますが、アップロード処理はコンポーネントとして作成する方がいいでしょうね。)
 
 
5行目では、アップロードするファイルを保存するパスを指定しています。
このパスの指定では、「WWW_ROOT」という定数を使って指定していますが、各種フォルダの位置を示す定数に関しては「   」にまとめましたので参考にしてみてください。
 
ドキュメントルートのパスや、「tmp」フォルダへのパスなどが規定されています。
 
 

ファイルアップロードの処理の関数本体

 
実際にファイルアップロードを行う本体の関数処理です。
 

 
 
各処理について解説します。
 
4~10行目。
ファイルを保存するフォルダとして指定する「$dir」の値が正しいかどうかをチェックしています。
「$dir」が空でないことと、「file_exists()」関数を使ってのフォルダの存在をチェックしています。
 
13~15行目。
アップロードするファイル項目が未定義であったり、複数のファイルが送信されてきたり、破損攻撃をするなど、不正な処理を受け付けた場合に無効にするための処理が記述されています。
 
18~30行目。
アップロードされたファイルのチェックを行います。
ファイルがない場合や、送信できるファイルの容量を超えている場合などのエラーチェックを行います。
 
33行目。
「tmp」フォルダにアップロードされたファイルの情報をチェックするため、file()オブジェクトを呼び出します。
 
36~38行目。
33行目の File()オブジェクトからファイルのサイズを取得し、引数で受け取ったサイズより小さいことをチェックします。
「$file[‘size’]」でもファイルサイズは取得できますが、File()オブジェクトの情報の方を信用していますので、そちらで処理をしています。
 
41~47行目。
File()オブジェクトから MIMEタイプを取得し、想定しているファイルタイプの中に存在するか否かをチェックするとともに、拡張子を取得します。
 
50行目、51行目
保存するファイル名を生成しています。
51行目は「$file[“tmp_name”]」を基にして、sha1_file()関数でファイル名を生成しています。
50行目は「$file[“name”]」としていまして、入力があったファイル名をそのまま使用する場合を想定しています。
 
ここは、どちらかを指定することを想定していますが、50行目の元のファイル名を使用する場合は、下記の不具合につながる可能性についての理解が必要です。
 ファイル名が重複する可能性
 全角文字(日本語)が文字化けする可能性
 
54~56行目
ファイル移動の処理本体です。
関数の引数として受け取ったフォルダ「$dir」に、「move_uploaded_file()」関数を使ってファイルを移動させることで、所定の場所にファイルが保存されたことになります。
 
ここまでいろいろな処理をしていますが、51行目までの処理は全てが入力チェックですので、入力チェックがなくていいならば、54行目のみでも OKです。
(入力チェックをしないのは現実的ではありませんが。)
 
59行目。
コメントアウトにしていますが、ここまで来たら正常に処理が終了したことになります。 
50行目、51行目で生成するファイル名を戻して処理終了です。
 
 
このファイルのアップロード処理に関しては、下記の処理を参考にしています。
https://secure.php.net/features.file-upload
 
「The following code cannot cause any errors absolutely.(次のコードはエラーを絶対に引き起こしません。)」と書いてありましたので、それを利用しました。
 
ただ、「move_uploaded_file()」関数は、正常にファイル移動ができない場合は、「false」を返すとともに、Warningを出力するため、CakePHP3ではそこで止まってしまいます。
 
そのため「@move_uploaded_file()」とすることで Warningを出さないように対処しています。
 
 

CakePHP3でファイルアップロードのまとめ

 
CakePHP3でファイルをアップロードするための処理を自作してみました。
 
ですが、この処理ではレコードを新規登録する際にファイルをアップロードする時には問題なく実行できるものの、レコードを更新する場合の画像の取り扱いや、ファイルだけを削除したい場合などの対処が十分ではないため実運用に使うにはもう少し処理を追加する必要があります。
 
それについては、下記に改めて記事を書きましたので、そちらを参照してください。
 CakePHP3で画像・ファイルのアップロード処理を自作・解説付き・その2
 
また、ファイルを保存する場所を指定するパス、および、画像を表示する際のドキュメントルートからのパスを取得する処理については、下記に記事を書いていますのであわせて参考にしてください。
 CakePHP3でDocumentRootやtmp、webroot、logsなどのフォルダへのパスの定数
 CakePHP3でDocumentRootやwebroot、imgフォルダのURLやドメイン、パスを取得

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

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

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP3のアソシエーション機能を使い関連レコードをまとめて削除

CakePHP3でレコードを削除する際に関連するレコードをまとめて削除する機能の解説。フレームワークのメリットを存分に発揮し、コマンドを1行追加するだけで実装可能。

MySQL、CakePHP 2.3で「tinyint(1)」の Boolean型の動作を再確認

MySQL+CakePHPの環境で「tinyint(1)」を利用する際の動作を検証。「tinyint(1)」の Boolean型について CakePHPでは自動処理が実施されていることを確認しました。

CakePHP 2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索

CakePHPの検索プラグイン Search Pluginの検索処理の中で前方一致検索、後方一致検索、不等号による検索、between句による範囲検索の解説です。

CakePHP 2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法

CakePHPの検索プラグイン Search Pluginの検索処理の中で動的に表示件数を変える方法です。

CakePHP3で値を入力直後にバリデーションする方法解説
CakePHP3で値を入力直後にバリデーションする方法解説

CakePHP3でバリデーションの実行を保存する時から入力情報を受け取るときに変更する処理の解説。CakePHP3ではnewEntity()の処理でバリデートするため1行追加で対応可能。

CakePHPを学ぶ際にはオブジェクト指向を学ぼう

CakePHPはオブジェクト指向で書かれていますので、CakePHPを学ぶにはオブジェクト指向も学びましょう。

CakePHP 2.3 コマンドラインからPHPのシェル実行の方法解説

CakePHP 2.3でコマンドラインから CakePHPで記述した処理を実行する方法を解説します。

CakePHP 2.3 Model、Controllerの見たい変数の中身をログ出力

CakePHPの Modelや Controllerの変数の中身をログとして出力して見る方法を提供します。

CakePHP3のインストールでURL rewriting......のエラーが!その解決方法解説
CakePHP3のインストールでURL rewriting……のエラーが!その解決方法解説

CakePHP3をインストールしたら URL rewriting is not properly configured.のエラーが。原因は.htaccessが有効になっていないこと。httpd.confに設定を追加すればOK。

CakePHP 2.3 テーブルの項目を演算した結果を条件として抽出する方法

アソシエーション(連携)している先のテーブルの項目で演算をする場合の考え方と注意点をサンプルソースを用いて説明しています。分かってしまえば簡単です。