🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

4264閲覧

HEROKUへデプロイ後、登録した画像が一定時間で消えてしまう

Ryota.I

総合スコア22

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

0クリップ

投稿2019/12/19 03:52

編集2019/12/19 11:06

お世話になります。

兼ねてより制作中だった画像投稿機能付のWEBサイトを、
HEROKUの無料枠でデプロイを行い完了までさせましたが、
その後、画像の登録操作をデプロイ後のWEB上から行い、
正常に表示までされることを確認し、一旦ブラウザを閉じ、
(体感ですが)1~2時間程経過後に再度WEBサイトを開き、
画像投稿済みの記事を見ると、画像部分だけ消えている状況でした。
この状況を改善する方法を調査中です。

今までの制作環境が、
AWS Cloud9:無料枠
MySQL:ver5.7.26
CakePHP:ver3.8.2
PHP:ver7.2.19
という内容であり、
その中ではその点について問題はなく、
この件について調べてみると、
HEROKUへデプロイ後の画像が消える問題の原因は、
"データベース内への画像データの保存方法にありそうだ"との判断に、
現在は至っています。
■参考記事:https://qiita.com/hmmrjn/items/b02f076ceaeeaaceb999
(Qiita:Railsではありますが本件と同内容と思われます)

今後、自身のWEBサイトの投稿後の画像をHEROKU上で消えないように
表示させる方法として、バイナリデータで保存していこうと判断しているのですが、

そもそも現在使用中の画像アップロードプラグイン
"josegonzalez/Upload Plugin 3.0"で、
バイナリデータの保存が可能なのかを現在は調べていますが、
公式ドキュメントを見ても、
はっきりとした仕様の確認ができない状況にあります。

一旦は、AWS Cloud9:無料枠の中で、カラムの追加やコード追記を行い、
バイナリデータを元に画像の投稿、表示まで確認できた後、
さらに、記事編集ページにある、「画像の差し替え」についても、
修正の上、改めてHEROKUへデプロイを予定していますが、
このプラグインの使用を前提とする改善プラン自体を、
見直す必要があるのか、またはこのプラグインを使用しつつも、
改善できるのか、ご教示いただけると助かります。
※「画像の差し替え」機能の参考記事
https://blog.s-giken.net/353.html
https://blog.s-giken.net/354.html
https://blog.s-giken.net/355.html

現在はDBへのバイナリデータ登録用のカラムの追加と、
追加したカラム分(image_binary)へのmodel内の追記まで、
済ませた状態です。この状況で画像の登録後、該当カラムへの登録された内容を見ると、
DB上で確認すると、「image_binary: image/jpeg」とあり、CakePHPのデバッグツールで
確認するとimage_binaryカラムに「0」と表示されています。

IcesTable.php

php

1public function initialize(array $config) 2 { 3 parent::initialize($config); 4 5 $this->setTable('ices'); 6 $this->setDisplayField('id'); 7 $this->setPrimaryKey('id'); 8 9 $this->addBehavior('Timestamp'); 10 11 $this->addBehavior('Josegonzalez/Upload.Upload', [ 12 'image_file' => [ 13 'keepFilesOnDelete' => false, 14 'nameCallback' => function ($data, $settings) { 15 return uniqid().'-'.strtolower($data['name']); 16 }, 17 'fields' => [ 18 'path' => 'webroot{DS}upload_img{DS}{model}{DS}{field}{DS}', 19 'dir' => 'image_file_path', 20 'size' => 'image_file_size', 21 'type' => 'image_binary'//今回の追記部分 22 ] 23 ] 24 ]); 25    //後略

MySQL

1//画像ファイルに関連するカラムのみ記載しています 2mysql> desc ices \G 3*************************** 1. row *************************** 4//中略 5*************************** 9. row *************************** 6 Field: image_file 7 Type: varchar(255) 8 Null: YES 9 Key: 10Default: NULL 11 Extra: 12*************************** 16. row *************************** 13 Field: image_file_path 14 Type: text 15 Null: YES 16 Key: 17Default: NULL 18 Extra: 19*************************** 17. row *************************** 20 Field: image_file_size 21 Type: int(11) 22 Null: YES 23 Key: 24Default: NULL 25 Extra: 26*************************** 18. row *************************** 27 Field: image_binary//バイナリデータの保存のための追加カラム 28 Type: mediumblob 29 Null: YES 30 Key: 31Default: NULL 32 Extra: 3318 rows in set (0.00 sec)

内容に不足があれば、追記しますので、随時教えていただきたいです。
お手数ですが、ご教示、お願いいたします。
また、参考となる、記事があればあわせて、
提示していただけるととても助かりますので、
あわせて、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

可能であれば、ファイルの保存先にはAWS S3などを利用するようにして、Upload系のプラグインを利用したほうが良いです。
FriendsOfCake/cakephp-upload だと、自前でS3へのアップロード部分を作らないといけないので、特にこだわりがなければ burzum/cakephp-file-storage を利用するのが良いかもしれません。


以下、データベースにファイルを保存するパターンのやり方です。
データベースに保存する場合、MySQLであれば max_allowed_packet の制限に引っかかる場合がありますので、適宜調整しましょう。

保存完了まで

1、DB上の該当テーブルに対し、バイナリデータを扱うカラムを追加。
(バイナリデータを入れる場所を事前に用意のため)

これは問題ないでしょう。ただ、image_binaryフィールドはEntityでhiddenに追加して、JSON等で出力されないようにしておくべきでしょう。
また、ファイルのmimeタイプを格納するフィールドを追加しておくと、出力時にちょっと楽ができます。

なお私が実装しているものでは、データテーブルとは別にファイル保存用にテーブルを作成しています。
(データのみ、ファイルも一緒に、と分けて取得しやすいため。また、ファイル単体で更新時刻が記録できるのでキャッシュしやすい

2、画像投稿に使用するController部に対し、バイナリデータを取得し、
保存するためのコードを記載。

これについては、TableクラスにbeforeMarshalを追加し、そこでアップロードファイルの取り出しとフィールドへのセットを行うようにするとよいです。

単純なサンプルだと以下です。

php

1 public function beforeMarshal(Event $event, ArrayObject $data) 2 { 3 $field = 'image'; // アップロードファイルのフィールド名 4 5 if ( 6 isset($data[$field]['tmp_name']) 7 && $data[$field]['error'] === UPLOAD_ERR_OK 8 && is_uploaded_file($data[$field]['tmp_name']) 9 ) { 10 $data['image_mime'] = $data[$field]['type']; 11 $data['image_binary'] = file_get_contents($data[$field]['tmp_name']); 12 } 13 }

保存した情報を表示するまで

これについては2通りのやり方があります。

1つは、バイナリを直接HTMLのimgタグにbase64エンコードして表示する方法、もう一方はファイルを出力するエンドポイントを作成して、そこを参照する方法です。

base64エンコード方式であれば、テンプレートを編集するだけです。簡易ですが、HTML自体に埋め込むためレスポンスが遅くなるデメリットがあります。

ファイルを出力するエンドポイントを作成する方法であれば、HTMLとは別にリクエストされるためHTMLのレスポンス自体は早くできます。
また、キャッシュしたり、フラグによってリサイズして出力したりと画像に対する操作をやりやすくなります。

icesテーブルのようですので、IcesControllerにimageアクション追加する感じで良いでしょう。

以下、簡易的なサンプルです。

php

1 public function image($id) 2 { 3 $entity = $this->Ices->get($id); 4 5 // Last Modified ヘッダーによるキャッシュハンドリング 6 // ices.modified に更新時刻が入っていると想定 7 $response = $this->response->withModified($entity->modified); 8 if ($response->checkNotModified($this->request)) { 9 return $response; 10 } 11 12 $this->response = $response; 13 14 $file = $entity->image_binary; 15 $type = $entity->image_mime; // image_mimeがないならバイナリデータからmimeタイプを取得する 16 17 // 画像の加工処理が必要であればここでバイナリに対して処理する。処理結果はキャッシュしておくとよい。キャッシュを利用する場合は、TableのafterSaveで対象のキャッシュ削除を行うようにする 18 19 return $this->response 20 ->withType($type) 21 ->withStringBody($file); 22 }

投稿2019/12/19 11:26

nojimage

総合スコア959

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Ryota.I

2019/12/20 03:46

nojimage様 お返事ありがとうございます。 昨晩いただいた内容の中で、 不明な単語の意味を一旦調べました。 その上で、ご提示いただいた内容の意味合いについて、 「こういう提案をしていただいたということでよいか」の すり合わせをさせていただきたいです。 ※今回の変更内容は、未熟ながらも多々変更箇所がある、 くらいの認識は持てたため、今もてる自身の思考能力をフル回転させ、 変更前にどういう方法が一番か、道筋を決めておきたいと考えております。 【以下、提示いただいた内容と、自身が認識できた意味】 ◎A:「可能であれば、」~「burzum/cakephp-file-storage を利用するのが良いかもしれません。」の内容まで◎ A-1:「画像ファイルの保存に使用する仕組み」は...  ⇒burzum/cakephp-file-storageがオススメ。画像の保存も表示もこのプラグインでできる。 A-2:「画像ファイルの保存先」は...  【今まで】MySQLの特定のテーブル内に記録していたし、バイナリの保存のためにimage_binaryフィールドを新たに設けたけど、  【今後】画像ファイルの保存先についてはMySQL内ではなくAWS S3に変更する。 ※それ以外のデータは今までどおりMySQLで。 ◎B :「以下、データベースにファイルを」~「保存完了まで」~「保存した情報を表示するまで」の内容まで◎ --- ・B-1:「画像ファイル」の保存先は「AWS S3」ではなく、今までどおり「MySQL」の使用を前提とし、 かつ、バイナリデータで記録していく場合。 ・B-2:(B-1が前提の元で)MySQLへバイナリデータとして保存した画像ファイルを表示する。 ご提示いただいた内容をA、Bにわけ、 今認識できている提示内容の意味合いを記載しました。 お手数をおかけしますが、ご教示をお願いいたします。
nojimage

2019/12/20 04:03

はい、その認識であっています。S3はアカウント登録から12ヶ月間は5GBほど無料で使えますが、それ以降は若干費用がかかります。転送量が数百Gになるなどトラフィックが多い場合はそれなりの金額になったりします。費用感は、https://aws.noplan.cc/s3/ あたりでざっくりわかります。
Ryota.I

2019/12/20 08:48

ご返答に加え、"ざっくりわかる~"のURLもありがとうございます。 今回に限らず、AWSを使用する上で参考ツールとして使わせていただきます。 ここまでの自身の認識が間違ってなくて安心しました。 ご返答いただいた内容を踏まえ、まずは... ・Amazon S3を使用できるようにする ・MySQL上に作成したimage_binaryフィールドは削除 ・プラグインはburzum/cakephp-file-storageへ変更(FriendsOfCake/cakephp-uploadは無効化、または削除) ・上記プラグインを使用の上、制作中WEBサイトから記事登録の際、画像はAmazon S3へ保存できるようにする 上記を手元の環境でクリアできるよう、作業していきます。 改めてHEROKUへのデプロイ後の挙動も問題ない所まで進められればベストですが、 不明点が出た際には、またこの質問記事でコメントさせていただきたいと思いますので、 よろしくお願いいたします。
Ryota.I

2019/12/21 08:01

nojimage様 昨晩より、いただいた返答内容を元に、 作業を進め、少しずつですが前進しています。 まだ、手元の環境で"画像の保存ができる"までには 至っていませんが、新たな不明点が出たため、 投稿させていただきました。 【実行した内容】 ・Amazon S3のアカウントを設定(cloud9と同じユーザで設定) ・Amazon S3のバケットの中にフォルダを作成 ・php composer.phar require aws/aws-sdk-phpをコマンド入力し、 AWS SDK for PHPをインストール(Using version ^3.130) ・php composer.phar require burzum/file-storageをコマンド入力し、 burzum/file-storageをインストール(Using version ^2.1) ・/src/Model/Table/IcesTable.php内に記載してあった、 josegonzalezのバリデーションの記載を削除 ↑ここまでは比較的スムーズにできました。 ↓以下に記載する内容は、自分が希望する結果を得るために、 本当に必要なのかはっきりしない状態で、実行した内容です。 【不明瞭ながら試したこと】 ・https://qiita.com/k-ando/items/668de29d15a19273e967(以下、Aとします)を 参照に、aws-sdk-phpインストール後の設定をしようと思い、 該当記事内の「.envファイルにS3への接続情報を書く」の部分のみ試しました。 その際、記載した文字の表現としては、Aの記事内を参考にしました。 (export ITEM_IMAGE_PATHからexport S3_VERSIONの表現をそのまま使用) ・また、「.envファイルにS3への接続情報を書く」に関連するものと判断し、 「CakePHPで.envファイルを有効化する」(以下、Bとします)の記事内の、 「config/bootstrap.php」のコメント解除を行いました。 ▽ここまでの参考記事であえてやっていないこと▽ ・Bの"configフォルダ配下にある.env.defaultを.envにリネームする" ⇒手元の環境で.envへリネームすると、そもそも制作していたWEBサイトの トップページが白画のみの状態となること、また、別記事で".env.default"をコピーしたファイルを ".env"へリネームし、".env"に接続情報を書く、という内容もありましたが、 この方法でも同様に白画になるため、一旦は.env.defaultに接続情報を記載した状況です。 ・同じくBの"config/app.php"のDatasourcesに続く内容で、 'username' => env('DB_USERNAME'), 'password' => env('DB_PASSWORD'), 'database' => env('DB_DATABASE'), ...を記載するように表記していますが、 今まで使用しているDBへの接続情報がこの部分に記載されているため、 ここを変更しては、他の情報の記録に影響が出ると思い、変更はしていません。 上記まで記載した内容で、 ・S3のアカウント設定 ・aws-sdk-phpのインストール ・burzum/file-storageのインストール ...は問題なく終わっていると思うのですが、 その先、どのようにburzum/file-storageとS3を紐付けるのか、 目先の目標とする、画像の投稿はどうしていくのか、 調査中ではありますが、はっきりしないことが多いという状況です。 お手数ですが、上述した内容に過不足がないか、 そしてどのようにburzum/file-storageとS3を紐付けるか、 また、できれば画像の投稿までの方法も加え、 改めてご教示いただきたいです。 ※長文となり申し訳ありません。
Ryota.I

2019/12/26 11:33

※現在の自身のスキルでは、調査と試行錯誤した結果、ご提案いただいたプラグインを使用すること自体が困難と判断したため、"プラグインを使用しない方法+画像保存先はAWS S3"という組み合わせに切り替え、作業を進めております。そのため、こちらの質問内容については、これでクローズとさせていただきます。また、ご提案いただいた内容については、そのままにせず、今後しっかり反芻し利用できるようにいたします。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問