エス技研

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


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

      2017/11/26

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
 

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

 
入力フォームに追加したファイルの入力項目「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」という定数を使って指定していますが、各種フォルダの位置を示す定数に関しては「CakePHP3でDocumentRootやtmp、webroot、logsなどのフォルダへのパスの定数」にまとめましたので参考にしてみてください。
 
ドキュメントルートのパスや、「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にWYSIWYGエディタのCKEditor4を設置、カスタマイズ方法を解説
CakePHP3でページごとに読み込むJavaScript、CSSを変える処理の解説
CakePHP3にデイトピッカー jQuery UI DatePickerを実装する手順の解説
CakePHP3の更新画面でUpload Plugin 3.0を使う方法、viewで使う方法解説・その3
CakePHP3のUpload Plugin 3.0をバリデーションなど実運用向けのカスタマイズ方法解説・その2
CakePHP3の画像、ファイルアップロードプラグインUpload Plugin 3.0の設置解説・その1
CakePHP3でユーザ定義の定数、変数を設定し、読み込む方法解説
CakePHP3のバージョンを指定してインストールする詳細な手順を解説
CakePHP3のタイムゾーンを協定世界時UTCから日本標準時間JSTにずれを変更する方法
CakePHP3チュートリアルで日付と時刻のDateTimeでエラーが出たときの対処方法
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

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

Message

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

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

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

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

  関連記事

CakePHP 2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索

CakePHPの検索プラグイン Search Pluginの検索処理の中で複数項目を入力した場合の AND検索、OR検索についての解説です。

CakePHP3でcomposerを利用してライブラリ・プラグインをインストールする方法

CakePHP3でcomposerを使ってパッケージ(ライブラリ、プラグイン)をインストールする方法の解説。PHPを使うのはCakePHP3が初めてというような方への使い方から解説。

CakePHP3のビューで受取ったテーブルのオブジェクトを連想配列に変換する方法
CakePHP3のビューで受取ったテーブルのオブジェクトを連想配列に変換する方法

コントローラーからビューに送ったテーブルのオブジェクトを連想配列に変換し、ビューの中で自由に使えるようにするメソッド「toArray()」の解説。連想配列に変換できれば利用度アップ!

CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法

CakePHPの検索プラグイン Search Pluginの検索処理の中で入力エリア一つで複数の項目を同時に検索する方法を解説。

CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合

アソシエーション(連携)している先のテーブルの項目で条件抽出する際の考え方と注意点をサンプルソースを用いて説明しています。

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

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

CakePHP3のcontroller内でテンプレート、レイアウトを変更する際の指定方法

CakePHP3でテンプレートファイルやレイアウトファイルをデフォルトのものから別のものに変更したい場合の指定方法を解説。

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

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

CakePHP3でDocumentRootやtmp、webroot、logsなどのフォルダへのパスの定数
CakePHP3でDocumentRootやtmp、webroot、logsなどのフォルダへのパスの定数

CakePHP3で特定フォルダのパスの定数を解説。root、DocumentRoot、app、config、webroot、tests、tmp、cache、vendor、コア、コアの srcが設定済み。realpath()関数を使うと柔軟なパス指定が可能。

CakePHP3チュートリアルで日付と時刻のDateTimeでエラーが出たときの対処方法
CakePHP3チュートリアルで日付と時刻のDateTimeでエラーが出たときの対処方法

CakePHP3のブックマークチュートリアルには記載ミスもあり、そのまま動かない個所もある。CakePHP3では namespaceを使うようになったので、classを呼び出すときに¥を追加する必要が!