画像をアップロードできる機能を、Rails & Paperclip で作ったときに気をつけたところ。 Rails は Heroku で動かして、画像は Amazon S3 に保存するもとのする。

概要

環境

  • rails 4.2.4
  • paperclip 4.3.1
  • aws-sdk 2.2.14

基本的なこと

Gem は最新のものを入れる

Gemfile

gem 'paperclip', :git => 'https://github.com/thoughtbot/paperclip.git'
gem 'aws-sdk', '>= 2.0.0'

paperclip 4.3.1 以上では、aws-sdk の 2.0 以上が使えるようになっている。

S3 を使う設定をする

Uploading Files to S3 in Ruby with Paperclip | Heroku Dev Center の "Configuration" の項、 および "International users (additional configuration)" の項を参考に設定する。

config/environments/production.rb

config.paperclip_defaults = {
  :storage => :s3,
  :bucket => ENV['AMAZON_S3_BUCKET_NAME'],
  :s3_region => ENV['AMAZON_S3_REGION'],
  :s3_host_name => ENV['AMAZON_S3_HOST_NAME'],
  :s3_credentials => {
    :access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
    :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
  }
}

設定は環境変数に出しておくと、Production 環境と Staging 環境を分けやすい。

キー
AMAZON_S3_BUCKET_NAME バケット名 my-app-image-bucket
AMAZON_S3_REGION リージョン ap-northeast-1
AMAZON_S3_HOST_NAME S3 のホスト名 s3-ap-northeast-1.amazonaws.com
AMAZON_ACCESS_KEY_ID アクセスキー ID --
AMAZON_SECRET_ACCESS_KEY シークレットアクセスキー --

アクセスキー ID およびシークレットアクセスキーは、最低限の権限(AmazonS3FullAccess)を持つユーザーを作成して、そのユーザーの Access Key を使うのが良いと思う。

注意点: リージョンを設定すること

aws-sdk 2.0 以上を使う場合、s3_region を設定する必要がある。

最新の paperclip を bundle install したときに、以下のメッセージを標準出力にプリントしてくれるので、スルーしないようにする。

##################################################
#  NOTE FOR UPGRADING FROM 4.3.0 OR EARLIER       #
##################################################

Paperclip is now compatible with aws-sdk >= 2.0.0.

If you are using S3 storage, aws-sdk >= 2.0.0 requires you to make a few small
changes:

* You must set the `s3_region`
* If you are explicitly setting permissions anywhere, such as in an initializer,
  note that the format of the permissions changed from using an underscore to
  using a hyphen. For example, `:public_read` needs to be changed to
  `public-read`.

Rails 以外で躓いたところ

バケットが非公開になっている

デフォルトではバケットは非公開設定になっているので、画像の URL にアクセスしても Access Denied のエラーが表示される。 解決するためには、以下の方法がある。

  • バケットポリシーを作成して、匿名ユーザーへのアクセス許可を付与する
  • バケットに作成されたフォルダを Make Public する

もちろん、ポリシーを作成する方法の方が良いと思う。ポリシーを作成する方法なら、特定の HTTP Referrer だけにアクセス許可を付与することもできるので。

バケットポリシーの例 - Amazon Simple Storage Service

まとめ・感想

  • Paperclip を使って S3 に画像をアップロードできた
  • Heroku のドキュメント に丁寧に解説があって分かりやすかった
  • Gem が新しくなったので、リージョンを設定する必要があった
  • S3 バケットが非公開になっていると、画像を読むことができない

Paperclip のお手軽感が良い。Heroku のマシンイメージに予め ImageMagick が入っているのがお手軽感を増している。