rails+AWS S3+carrierwaveで画像を保存する

目次

マーケター、エンジニアを月1時間からジョインできるプラットフォーム

airteamは月1時間からマーケターやエンジニアに相談できるプラットフォーム。 雇うのはハードル高いけどプロをチームに入れたい。そんな経営者のためのサービスです。 相談にのる方も募集しています。

タスクなしだから月一時間からジョイン可能

作業はなくオンライン相談メイン。 月1時間からさっと経験者に継続的に相談できます。

多様な経験者を雇用するより何倍も早くチームに

あらゆるジャンルの経験者がいるので あなたのチームのノウハウの選択肢が広がります。

NDAはすでに締結済み、契約もスムーズ

契約の煩雑なやりとりはなく、NDAはすでに締結済み、書面のやりとりはありません。

railsでcarrierwaveとAWSのS3を使って画像保存を開発したので手順をまとめていきます。

環境は下記になります。

  • rails7
  • AWS S3

全体の流れ

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

AWSアカウント作成

AWSの準備をします。やるのは下記で今回はIAMは発行済みという前提でS3バケット作成時に気になる項目をまとめます。

  • IAM発行
  • S3でバケット作成

バージョニングとは

下記の記事が詳しかったです。ざっくりいうと保存した画像のバージョンを保存することで復元したりすることができます。

https://dev.classmethod.jp/articles/3minutes-s3-versioning-lifecycle/

データ暗号化

AWS S3 (Amazon Simple Storage Service)は、データ暗号化をサポートしています。特にデフォルトの設定では、ユーザーがデータ暗号化を明示的に要求しない限り、データは暗号化されません。しかし、S3は、データを保管する際に、サーバーサイドとクライアントサイドの両方で暗号化をサポートしています。

サーバーサイド暗号化には以下の3種類があります:

  1. S3マネージドキー (SSE-S3): 各オブジェクトに対してAmazon S3が一意のキーを生成し、そのキーをさらにマスターキーで暗号化します。
  2. AWS Key Management Service, マネージドキー (SSE-KMS): このオプションは、AWS KMSを使用してユーザーのデータキーを暗号化します。これは、AWS CloudTrailと統合されており、キーの使用を追跡し、オブジェクトへのアクセスを監査する機能を提供します。
  3. カスタマー提供キー (SSE-C): 顧客が自分の暗号化キーを提供するオプションです。

クライアントサイド暗号化では、データは送信前に暗号化され、S3に送られてから、クライアントによって復号化されます。

Amazon S3のバケットポリシーを使って、すべての新しいオブジェクトに対するサーバーサイド暗号化を強制することも可能です。これにより、新しいデータが暗号化されて保存されることが保証されます。

また、AWSのS3でデータを転送する際は、SSLを用いた安全なデータ転送が可能で、データ転送中の暗号化を実現します。

gem fogとcarrierwaveのinstall

gem 'carrierwave'
gem 'fog-aws'

上記でgem install。

カラム追加

S3のurlを格納するカラムを追加

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

carrierwaveの設定

uploaderクラスの追加

rails generate uploader Image

上記でImageUploaderを作成し、下記コードを。

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

  include CarrierWave::MiniMagick
  process resize_to_limit: [500, 500]

  def extension_allowlist
    %w(jpg jpeg gif png)
  end

  # ここでファイル形式を指定する
  def filename
    original_filename if original_filename
  end

end

コードの解説は下記。

  1. storage :fog: このコードは、fogストレージエンジンを使用してファイルを保存することを指定しています。fogは、様々なクラウドストレージサービス(Amazon S3など)と連携するためのRubyライブラリです。このコードは現在、開発(development)環境、テスト(test)環境、その他の環境(恐らく本番production環境)すべてでfogを使用するよう設定されています。もし環境ごとにストレージエンジンを変えたい場合は、この部分を適宜修正します。
  2. store_dir: アップロードされたファイルの保存場所を定義しています。ここでは"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"というパスにファイルが保存されます。この中の#{model.class.to_s.underscore}はモデルのクラス名(小文字とアンダースコア)を、#{mounted_as}はマウンタ名(つまり、どの属性にこのアップローダが紐づけられているか)を、#{model.id}はモデルのIDをそれぞれ表しています。
  3. include CarrierWave::MiniMagickprocess resize_to_limit: [500, 500]: これらのコードは、MiniMagickという画像処理ライブラリを使用して、アップロードされた画像を処理(ここでは、幅と高さが最大500ピクセルになるようにリサイズ)することを指定しています。
  4. extension_allowlist: アップロードを許可するファイルの拡張子を定義しています。ここではjpgjpeggifpngの4つの拡張子を持つファイルのみがアップロードを許可されています。
  5. filename: 保存するファイル名を定義しています。ここでは、元のファイル名(original_filename)が存在する場合、その名前を使用してファイルを保存します。ファイル名を変更する必要がある場合は、このメソッドを修正します。

initializersの設定

下記を新規作成。

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
    aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
    region: 'ap-northeast-1'
  }

  config.fog_directory  = ENV["DIRECTORY_NAME"]
  config.asset_host = ENV["ASSET_HOST"]
  config.cache_storage = :fog
  config.fog_public = false
  config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
end
  1. CarrierWave.configure do |config| : CarrierWaveライブラリの設定を開始します。configオブジェクトを使って、設定オプションを指定します。
  2. config.fog_credentials : ここでAmazon S3に接続するための認証情報を指定します。’AWS’はプロバイダとしてAmazonを指定していることを示しています。以下のaws_access_key_idaws_secret_access_keyは、S3にアクセスするために必要な認証キーです。regionはAWSのリージョンを指定します。ここでは ‘ap-northeast-1’(東京リージョン)が指定されています。
  3. config.fog_directory = ENV["DIRECTORY_NAME"] : アップロードされたファイルを保存するS3のバケット(ディレクトリ)名を設定します。
  4. config.asset_host = ENV["ASSET_HOST"] : ファイルへのURLが生成される際のベースURLを指定します。アセットホストが指定されると、生成されるURLはこのホストを基にします。
  5. config.cache_storage = :fog : アップロード前のキャッシュストレージとしてS3を使用することを指定します。これにより、アップロード前の一時的なファイルもS3上に保存されます。
  6. config.fog_public = false : ファイルへのアクセスを非公開にします。falseに設定すると、生成されるURLは署名付きURLとなり、一定時間経過後にアクセスできなくなります。
  7. config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } : S3にアップロードされるファイルに対するHTTPヘッダのデフォルト設定を行います。ここでは、cache_controlヘッダを設定して、ブラウザがキャッシュをどの程度の期間保持すべきかを指示しています。ここでは最大365日間キャッシュを保持するように設定されています。

リージョンは下記から選ぶ。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html#s3_region

modelにmount_uploader

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

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

アップロード機能(view)

<%= form_with model: @user,url: update_path,method: :patch, local: true do |form| %>
  <%= form.file_field :icon_url %>
<% end %>

保存した画像の表示

<%= image_tag photo.image.to_s %>