エス技研

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


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

      2017/10/28

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やドメイン、パスを取得
 
 

CakePHP3の関連記事

CakePHP3でユーザ定義の定数、変数を設定し、読み込む方法解説
CakePHP3のバージョンを指定してインストールする詳細な手順を解説
CakePHP3のタイムゾーンを協定世界時UTCから日本標準時間JSTにずれを変更する方法
CakePHP3チュートリアルで日付と時刻のDateTimeでエラーが出たときの対処方法
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
CakePHP3のCakeDC/UsersのUserHelperでログアウトやreCAPTCHAをカスタマイズ
CakePHP3のCakeDC/Usersのログイン後のリダイレクトを設定解説
CakePHP3のCakeDC/Usersの画面、メール本文テンプレートのカスタマイズ方法解説
CakePHP3のユーザ管理・認証プラグイン CakeDC/Usersの導入・機能解説・3.1.5対応
CakePHP3ログファイルの出力方法・$this->log()の解説
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

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

Message

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

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

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

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

  関連記事

CakePHP 2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索

CakePHPの検索プラグイン Search Pluginの検索処理の中で queryを使って日付の範囲検索の方法です。

CakePHP3ログファイルの出力方法・$this->log()の解説
CakePHP3ログファイルの出力方法・$this->log()の解説

コントロール、モデルの変数の中身を見るときはログに出力する方法が有効です。$this->log()を利用すると変数だけじゃなく、連想配列、オブジェクトも簡単にログ出力ができます。

CakePHP 2.x系 Viewでのコメントの記述方法など

CakePHPにおいて View、ctpファイルでコメントを記述する方法を解説。

CakePHP3のCakeDC/UsersのUserHelperでログアウトやreCAPTCHAをカスタマイズ
CakePHP3のCakeDC/UsersのUserHelperでログアウトやreCAPTCHAをカスタマイズ

CakeDC謹製Usersプラグインの紹介。UserHelperを利用し、ログアウトのリンクや権限があるときのみ表示されるリンク、プロフィールページへのリンク、reCAPTCHAの設置方法などを解説。

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

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

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

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

CakePHP 2.3で saveの便利な使い方・サンプルソース付き

CakePHPのレコードを保存、更新する際に使う Saveを詳細解説します。

CakePHP 2.3でファイルをアップロード・その2 ファイル名を乱数で設定

CakePHPのアップロードするファイル名を乱数で変更しセキュリティを高める方法を解説。

CakePHP3のタイムゾーンを協定世界時UTCから日本標準時間JSTにずれを変更する方法
CakePHP3のタイムゾーンを協定世界時UTCから日本標準時間JSTにずれを変更する方法

CakePHP3の標準設定のタイムゾーンは「UTC(協定世界時)」に設定されている。これを日本標準時に変更する方法(app.php、bootstrap.phpの変更方法)の解説。

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

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