LoginSignup
14
17

More than 3 years have passed since last update.

HerokuでS3に画像をアップロードした話[Rails][S3][CarrierWave][fog]

Posted at

転職活動用にポートフォリオを作っています。
DTPの作品も多く、画像が全部でおよそ18MBあったのですが、Herokuの無料版の容量は5MBのため、画像の外部ストレージとしてS3を利用するようにしました。

調べたら、多くの人がつまづいているようでしたので、自分のためにも手順をメモしておこうと思います。

S3の利用設定

まずは、S3の利用設定を行います。手順については、こちらのサイトを大変参考にさせていただきました。

【Rails】S3へ『CarrierWave+fog』を使って画像アップロードする方法

↑こちらの記事以上に丁寧な説明はないと思いますので、S3の設定についてはこちらをご参照いただければ幸いです。

gemをインストール

画像アップロードに必要な、以下のgemをインストールします。

  • carrierwave…画像をアップロードするgem
  • mini_magick…画像をリサイズするgem
  • fog…S3などのクラウドストレージ内の画像を参照するgem

それぞれ、設定の書き方は以下の通り。

Gemfile
group :production do
  gem 'pg',             '0.18.0'
  gem 'rails_12factor', '0.0.2'
  gem 'fog-aws'
end

gem 'carrierwave'
gem 'mini_magick'

忘れずにbundle installします。

なお、私の場合ですがfogというgemではaws関連のdependencyのgemがインストールされず、fog-awsを利用しないと先に進めませんでした。

アップローダーの生成

 CarrierWaveをインストールすると、画像のアップローダーの生成ができるようになりますので、以下のコマンドで生成します。

$ rails generate uploader カラム名

最後の「カラム名」は、画像を必要とするモデルのデータベースのカラム名です。単数形、頭文字大文字で表記します。私は、すでにあったテーブルのカラム名から、Imageにしました。

なお、画像のファイル名が文字列のため、imageカラムのデータ型はstring型です。

$ rails generate uploader Image
      create  app/uploaders/image_uploader.rb ←生成

CarrierWaveに、imageカラムがuploaderと関連していることを認識させるためには、mount_uploaderというメソッドを使います。(今回モデル名はwork

models/work.rb
class Work < ApplicationRecord
  mount_uploader :image, ImageUploader
end

 viewファイルの書き換え

そして、今度はビューファイルをいくつか変更します。まずは、ファイルをアップロードする機能をviewに持たせます。画像をアップロードするフォームのタグをfile_fieldにしました。

views/works/new.html.haml
= f.label :image, "画像:"
= f.file_field :image

そして、workの一覧ページの書き方も、CarrierWaveに合わせて書き換えます。

views/index.html
-# 書き換え前
- @works.each do |work|
   = image_tag work.image

-# 書き換え後
- @works.each do |work|
  = image_tag work.image.url

work.imageの後にurlをつけるのがポイントです。
以上の動作により、無事画像のアップロードができました。

Image from Gyazo

本番環境で画像のアップロード先を変える

この時、画像ファイルはデフォルトでは、ローカルのフォルダにアップロードさせています。

views/uploaders/image_uploader.rb
storage :file

storage :fileという記述は、ローカルのファイルシステムに画像を保存するための記述です。

画像で示すと、こちらにありました。
Image from Gyazo

これだと、Herokuにデプロイした時に容量を圧迫してしまうので、本番環境だけS3に画像をアップするようにしたいと思います。

views/uploaders/image_uploader
if Rails.env.production?
  storage :fog
else
  storage :file
end

if Rails.env.production?で本番環境ではクラウドストレージに保存するようにしています。
さらに、同じく、image_uploaderに下記のように記載します。

views/uploaders/image_uploader
if Rails.env.production?
    CarrierWave.configure do |config|
      config.fog_credentials = {
        # Amazon S3用の設定
        :provider              => 'AWS',
        :region                => ENV['S3_REGION'],  # S3に設定したリージョン。
        :aws_access_key_id     => ENV['S3_ACCESS_KEY'],
        :aws_secret_access_key => ENV['S3_SECRET_KEY']
      }
      config.fog_directory     =  ENV['S3_BUCKET']
    end

それぞれ、以下のように設定します。ちなみに、東京のリージョンはap-northeast-1です。

$ heroku config:set S3_ACCESS_KEY="S3のAccessキーを入力"
$ heroku config:set S3_SECRET_KEY="同様に、Secretキーを入力"
$ heroku config:set S3_BUCKET="Bucketの名前を入力"
$ heroku config:set S3_REGION="Regionの名前を入力"

ここまで書いたらようやく本番環境にデプロイです。デプロイして動作を試します。

・・・できた!!!無事アップロード完了です!!

Image from Gyazo

追伸:エラーへの対処

なお、本番環境ではすぐに順調に動作をしたわけではなく、私の場合はAccess Deniedというエラーに遭いました。

S3のパブリックアクセス設定を変更するを変更したところ、なんとかなりましたので、ここに情報を共有しておきます。
Image from Gyazo

14
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17