やりたいこと
画像を投稿できるようにしたいが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
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の設定
下記のファイルを新規作成する
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 %>