carrierwaveかpaperclipを使って画像URLからS3にアップロードする

hatappi.hateblo.jp

前回に続いて今回もRailsで素振り

今回やりたいこと

Railsで画像URLを指定してダウンロードしたものをS3にアップロードする!!
例えば次のような画像
https://pbs.twimg.com/profile_images/896275871941574656/wAcSCGy4_400x400.jpg

候補

今回はアップローダーを使って実現を試みる
対象は次の2つ

github.com

github.com

Carrierwave

まずはcarrierwaveから

github.com

Gemfileに次の2つのgemを追加します

gem 'carrierwave'
gem 'fog-aws'

次にモデルを作成します

$ bundle exec rails g model CarrierwaveImage image:string

carrierwaveのUploaderを作成します
これはgeneratorが付いているので次のように指定します

$ bundle exec rails g uploader Image

中身はこんな感じで設定します
今回は最低限の設定だけしているので細かい設定はGithubREADMEを見てください

class ImageUploader < CarrierWave::Uploader::Base
  storage :fog
  
  def store_dir
    "test/carrier_wave"
  end
end

次にcarrierwaveのinitializerを追加します
config/initializers/carrierwave.rb

CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: ENV['AWS_ACCESS_KEY'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
    region: 'ap-northeast-1'
  }
  config.fog_directory  = 'test_bucket' # S3のバケット名
  config.cache_storage = :fog
end

最後にさきほど作成したUploaderをモデルの指定したカラムにマウントします

class CarrierwaveImage < ApplicationRecord
  mount_uploader :image, ImageUploader
end

実行

carrierwaveはモデルにremote_[マウントしたカラム名]_url=というメソッドがはえるのでそこにダウンロードしたい画像URLを指定してsaveするとアップロード処理が実行される

> c = CarrierwaveImage.new
> c.remote_image_url = "https://pbs.twimg.com/profile_images/896275871941574656/wAcSCGy4_400x400.jpg"
> c.save!

Paperclip

次はpaperclip

github.com

Gemfileには次のように追加します

gem 'paperclip'
gem 'aws-sdk'

paperclipようのモデルを追加します

$ bundle exec rails g model PaperclipImage image:attachment

attachementはpaperclipで定義されているもので、migrateすると次のカラムがテーブルに生成されます

次にenvironmentにpaperclip用の設定を追加します

Rails.application.configure do
~~~
  
  config.paperclip_defaults = {
    storage: :s3,
    bucket: 'test-bucket',
    s3_region: 'ap-northeast-1',
    s3_host_name: 's3-ap-northeast-1.amazonaws.com',
    s3_credentials: {
      access_key_id: ENV['AWS_ACCESS_KEY'],
      secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
    }
  }

end

paperclip用のinitializerを作成します

config/initializers/paperclip.rb

Paperclip::UriAdapter.register

最後はモデルにpaperclipの設定を追加します

class PaperclipImage < ApplicationRecord
  has_attached_file :image, path: "test/paperclip/:filename"
  
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end

実行

> pi = PaperclipImage.new
> pi.image = URI.parse("https://pbs.twimg.com/profile_images/896275871941574656/wAcSCGy4_400x400.jpg")
> pi.save!

最後に

今回はcarrierwaveとpaperclipを使って画像URLを指定してS3にアップロードを行いました。
個人的にはUploaderクラスとして分けるcarrierwaveが好きです