LoginSignup
22
45

More than 3 years have passed since last update.

rails+heroku+aws s3の構成で画像を保存する

Last updated at Posted at 2018-05-01

やりたいこと

画像を投稿できるようにしたいがherokuだと一時的な保存になるということなのでawsのs3に保存する。

全体構成

調べてみると2つ実装方法があった。今回はcarrierwaveを選択。

paperclip

paperclip
https://github.com/thoughtbot/paperclip

carrierwave

carrierwave
https://github.com/carrierwaveuploader/carrierwave

全体の設計

  • carrierwaveを使い、fileuploaderの作成
  • fogでawsのs3に繋ぎ、s3に画像を保存
  • URLを画像に付与してそのURLを元に表示

awsアカウント作成

この記事のアカウント作成部分を参考に。バケットの状態については下記

  • Public – 世界中の誰でも、または認証された AWS ユーザーがパブリックアクセス可能。
  • Not public* – バケットはパブリックアクセス可能ではありません。ただし、バケットのオブジェクトは、オブジェクト ACL によりパブリックアクセス可能の場合があります。
  • Access denied – バケットからロックアウトされています。
  • Error – サービス関連のエラーが発生しました。
  • Undetermined – Amazon S3 はバケットがパブリックアクセス可能かどうかを判断できません。

fogとcarrierwaveのinstall

gem 'carrierwave'
gem 'fog-aws'

ここがfogのまんまだと下記の記事のようなエラーが出る

画像保存用のモデル作成

新規のモデルに追加する場合

$ rails g model image
class CreatePhotos < ActiveRecord::Migration
  def change
    create_table :photos do |t|
      t.string :image
      t.timestamps
    end
  end
end

既存のモデルに追加する場合

$ rails g migration addcolumnimage
class AddColumnimage < ActiveRecord::Migration[5.1]
  def change
    add_column :image, :string
  end
end

carrierwaveの設定

uploaderクラスの追加

rails generate uploader Image
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  if Rails.env.development?
    storage :fog
  elsif Rails.env.test?
    storage :fog
  else
    storage :fog
  end

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_whitelist
    %w(jpg jpeg gif png)
  end
  # ここでファイル形式を指定する
  def filename
    original_filename if original_filename
  end
end

storage・・・storageでは画像の保存先を設定している。ここをlocalの開発環境でもawsに保存したい場合はfogにする。上記では全部fogだから分岐必要ないが、環境ごとに変えるなら変更する必要あり。
store_dir・・・fileのupload先を変更したいときに設定する。

initializerの設定

下記のファイルを新規作成する

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: '',
    aws_secret_access_key: '',
    region: 'ap-northeast-1'
  }

  config.fog_directory  = 'rails-photo-123'
  config.asset_host = "https://s3.ap-northeast-1.amazonaws.com/バケット名"
  config.fog_public = false
  config.cache_storage = :fog
end

aws_access_key_id・・・awsのiamのaccesskey
aws_secret_access_key・・・awsのiamのsecretaccesskey
config.fog_directory・・・バケット名
config.asset_host・・・https://s3.リージョン名.amazonaws.com/バケット名

fog_publicを利用することで、URLへの直アクセスを制御できる。 デフォルトはtrueらしい。 これがtrueの場合は、アップロードしたオブジェクトのアクセス許可に、 全員ダウンロードができる権限が付与される。

fog_publicについては上記。基本はs3のブロックパブリックアクセス (バケット設定)を全てonにしてパブリックで見れないようにしてこのfog_publicもfalseにすることでパブリックにアクセスできないようにする方がセキュリティ的には良い。

region

各regionの表

modelにmount_uploader

class Post < ActiveRecord::Base
  mount_uploader :image, ImageUploader
end

引数に(カラムの属性名, 生成されたアップローダーのクラス名)をとります。

view側の設定

form_forでタグ設置

入力用のformタグはform_forで生成する

<%= form_for @post, :url => {:action => 'create'} do |f| %>
<%= f.file_field :image %>
<% end %>

form_forで生成するとpostの下に配列が入る。なのでparamsで取ってくるときは下記のように[:post][:image]のような形になる。

@post = Post.new(title:params[:title],sns_id:params[:sns_id],sns:params[:sns],image:params[:post][:image],user_id:params[:user_id],description:params[:post][:description],post_type: params[:post_type])

form_forについてはこの記事が詳しい。

保存した画像を表示させる

<%= image_tag photo.image.to_s %>
22
45
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
22
45