LoginSignup
18
19

More than 5 years have passed since last update.

[Rails4]CarrierWaveを使ってs3に画像をアップロードする

Posted at

いくつか方法はあるみたいなんですが、s3バケット内にディレクトリも作らせたかったので、今回はPaperclipを使うことにしました。
userモデルはすでにあって、そこにプロフ画像を追加します。

環境
Rails4.0.0
Ruby2.0.0-p246

参考URL
RailsでPaperclipを使ってAmazon S3に画像を保存する
http://www.aguuu.com/archives/2012/12/paperclip/

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

下準備

S3にアクセスするユーザを作成する

その際に、Access Key IDとSecret Access Keyをメモしておく

S3にバケットを作成

image-upload
とか本番・開発で分けたかったら分けて立てる
先ほど作成したユーザにpermissionタブから割り当てるのを忘れずに。(権限は、show/edit permissionは外していいと思う)

Gemfileに登録

gem 'paperclip'
gem 'aws-sdk'
bundle install

ここから本番

DBに画像保存用のカラムを追加

DBに保存と言っても、画像そのものじゃなくて画像ファイル名とかコンテントタイプとかの保存に使うようです。

rails generate paperclip user avatar
      create  db/migrate/20140424060535_add_attachment_avatar_to_users.rb

migrationファイルの中はこんな感じ。

add_attachment_avatar_to_users.rb
class AddAttachmentAvatarToUsers < ActiveRecord::Migration
  def self.up
    change_table :users do |t|
      t.attachment :avatar
    end
  end

  def self.down
    drop_attached_file :users, :avatar
  end
end

migrateする

rake db:migrate

S3の設定ファイルを作成する

東京リージョンにs3を立てた場合は、host_nameはs3-ap-northeast-1.amazonaws.com固定っぽい。

config/s3.yml
bucket: image-upload
access_key_id: IAMで作成したユーザのkey_id
secret_access_key: IAMで作成したユーザのaccess_key
s3_host_name: s3-ap-northeast-1.amazonaws.com

本番環境とstg環境でバケットを分けたい場合は、環境毎に書けるみたい。

userモデルにアタッチするファイルの情報を記述する

以下を記述すればOK。pathはここでは更新時間をファイル名にしているけど、ハッシュ値とか他にも使えるよう。

user.rb
  has_attached_file :avatar,:storage => :s3,
    :s3_credentials => "#{Rails.root}/config/s3.yml",
    :url => "s3_domain_url",
    :path => ":attachment/:id/:updated_at.:extension"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
users_controlloer.rb

  current_user.avatar = user_params

  def user_params
    params.require(:user).permit(:avatar)
  end

これだけでs3へ保存が出来ました!簡単!

ドハマりポイント

保存自体はすぐに出来たんだけど、s3に置いたファイルのURLが取れなくて右往左往してました。。。
DBに保存してあるファイル名とURLが別ってちょっと詐欺チックだと思う。
ちなみに、DBに保存されるファイル名は、元ファイルのファイル名。

# avatar.path はpathで設定した内容が返ってくる→相対パス
avatar.path
=>/avatar/1111/123456789.png
# avatar.path は実際にs3に置いたパスが返ってくる→絶対パス
avatar.url
=>http://s3-ap-northeast-1.amazonaws.com/hogehoge/avatars/1111/123456789.png?123456789

んで、urlを取れるようになったはいいけど、クエリに更新時間(ファイル名)がついてる。。なんでやー。
クエリなしにしたかったけど、よくわからなかったので、クエリ部分をsplitして端末に返すという荒業をしましたw
画像のキャッシュ対策なんだろうか。。
にしても、urlってどこで持ってるんだろう。。メモリかな?
未だになれないRailsのよろしく感。

18
19
1

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
18
19