Help us understand the problem. What is going on with this article?

画像投稿がメインのサービスをはじめて運営してみて、失敗したこと、改善したこと、やろうとしていること

こんにちは、キッド✈️と申します。
東南アジア発のスタートアップスタジオ、GAOGAOのサーバーサイドエンジニアです。
このQiitaはGAOGAO Advent Calendar 2019の25日目の記事です。

先日、@rikuhiroseさんと共同で開発している、旅行サービスをリリースしました。ユーザーによる画像投稿がメインになるサービスです。

リリースしたサービスはこちらです。
20191214003023.png
FRIP | 思わず友達を旅行に誘いたくなる、 おすすめなスポットがあつまる旅行口コミサイト

実は、ユーザーによる画像投稿がメインのサービスを運営するのはこれがはじめてです。

実際に画像投稿メインのサービスを運営してみて、失敗したことがあったので、備忘録としてこちらに残すことにしました。

失敗したこと

(1)ファイルサイズが大きい画像のアップロードに失敗する

サービスをリリースしてすぐ、ありがたいことに友達が投稿をしてくれようとしました..!!嬉しい!!

と、喜んだのもつかの間。

投稿フォームを入力し、投稿する画像を選択し、いざアップロードしたら、画像が重すぎてエラーになりました。

スクリーンショット 2019-12-24 22.46.53.png

理由としては、PHPのupload_max_filesizeを超えてしまったために、サーバー側まで画像を渡すことができませんでした。

お恥ずかしいのですが、PHPのupload_max_filesizeの上限を変更しておらず、上限に引っかかってしまったのです。

解決策:

php.iniのpost_max_sizeとupload_max_filesizeの上限を変更しました。

FRIPはHerokuで運用しています。

HerokuでPHPのupload_max_filesizeを変更するには、publicディレクトリ配下に、.user.ini という名前のファイルを作成し、そちらに書き込むことで反映させることができます。

.user.ini
post_max_size = 20M
upload_max_filesize = 5M

(2)投稿に30秒以上かかってしまう

さて、upload_max_filesizeの上限をあげたことで、無事にサイズの大きな画像もアップロードできるようになりました。しかし、今度は別の問題が発生しました。

リリース当初、画像アップロードは、フォーム送信後にサーバーサイドで全てアップロード処理を行っていました。

スクリーンショット 2019-12-24 23.29.28.png

ですが、ファイルサイズの大きい画像で、かつ複数枚ともなると、フォーム送信してから完了するまでの時間が長い長い...。計測したら、フォーム送信から完了まで30秒かかってしまうこともざらにありました。

これではユーザーが使ってくれない...。

解決策:

画像アップロードは、画像を選択したら非同期でアップロードを行い、アップロードして画像のidを返すようにしました。

フォームを全て入力し、送信する時点で、画像はアップロードされるようにしたことで、フォーム送信から完了までの時間を大幅に短縮することができました。

(3)ファイルサイズが大きすぎてサイトが劇的に遅くなる

さて、無事に投稿はスムーズにできるようになりました。

しかし、今度はユーザーがアップロードした画像のファイルサイズが大きすぎて、サイトが劇的に遅くなりました...。

画像アップロードはS3にアップロードして、テーブルにs3へのurlを保存。CloudFront経由でS3の画像を読み込んでいました。

お恥ずかしいのですが、ユーザーがアップロードした画像は何も改変せず、そのままS3にあげていました。

旅行系サービスなのでユーザーが投稿する画像は、ファイルサイズが大きくなりがちです。

スクリーンショット 2019-12-24 22.40.44.png

トップページで152 × 152 pixelsでしか表示していないのに、読み込んでいる画像は4032 × 3024 pixels。そりゃ重くなるわけだ..。

今現状、投稿は16個ほどですが、読み込みが劇的に遅くなってしまいました。

解決策:

画像をリサイズ後に、S3へアップロードするようにしました。

FRIPはLaravelを使っているのですが、Laravel向けのライブラリで、簡単に画像をリサイズできるIntervention/imageがあり、こちらでリサイズする処理を入れました。

画像をS3にアップロードする前にこちらの処理を入れています。このように書くことで、width:600で、画像のアスペクト比を維持したままリサイズすることができます。

image.php
\InterventionImage::make($image)
  ->resize(600, null, function ($constraint) {
  $constraint->aspectRatio();
  $constraint->upsize();
})->save();

また、こちらのリサイズ機能を追加する前に投稿された画像は未対応なままです。

そちらについては、今後はCloudinaly経由でリサイズして配信する予定しています。

今後やること

Cloudinalyから画像配信

現在は、画像アップロードまでに画像を一定のサイズにリサイズしてから、S3にアップロードし、CloudFront経由でS3の画像を読み込んでいます。

しかし、将来的にはデバイスごとに配信する画像のサイズを改変したいと思いました。

そこで便利なのが、Cloudinalyです。

Cloudinalyでは、画像のパスに「w_500」と、widthを指定するだけ、そのサイズにリサイズしてくれます。
https://res.cloudinary.com/frip/image/upload/c_scale,w_500/v1574897562/sample.jpg

すでにS3で画像管理していても、CloudinalyならリソースURLのパスを紐づけるマッピング設定を行うことで、即時に自動アップロード・画像変換を行うことができます。

詳しくはこちらの記事に解説を譲ります。僕もこちらの記事を参考に設定しました。
S3 から Cloudinary への自動アップロードで即時に画像変換する|クラスメソッドブログ

最後に

記事からも分かりますように大変未熟ですので、画像アップロードのフローで、もっとこうした方がいいよ!など改善アドバイスやフィードバックいただけたらすごく嬉しいです🙇‍♂️

何卒よろしくお願いいたします🙇‍♂️

メリークリスマス!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした