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種類があります:
- S3マネージドキー (SSE-S3): 各オブジェクトに対してAmazon S3が一意のキーを生成し、そのキーをさらにマスターキーで暗号化します。
- AWS Key Management Service, マネージドキー (SSE-KMS): このオプションは、AWS KMSを使用してユーザーのデータキーを暗号化します。これは、AWS CloudTrailと統合されており、キーの使用を追跡し、オブジェクトへのアクセスを監査する機能を提供します。
- カスタマー提供キー (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
コードの解説は下記。
-
storage :fog
: このコードは、fog
ストレージエンジンを使用してファイルを保存することを指定しています。fog
は、様々なクラウドストレージサービス(Amazon S3など)と連携するためのRubyライブラリです。このコードは現在、開発(development
)環境、テスト(test
)環境、その他の環境(恐らく本番production
環境)すべてでfog
を使用するよう設定されています。もし環境ごとにストレージエンジンを変えたい場合は、この部分を適宜修正します。 -
store_dir
: アップロードされたファイルの保存場所を定義しています。ここでは"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
というパスにファイルが保存されます。この中の#{model.class.to_s.underscore}
はモデルのクラス名(小文字とアンダースコア)を、#{mounted_as}
はマウンタ名(つまり、どの属性にこのアップローダが紐づけられているか)を、#{model.id}
はモデルのIDをそれぞれ表しています。 -
include CarrierWave::MiniMagick
とprocess resize_to_limit: [500, 500]
: これらのコードは、MiniMagickという画像処理ライブラリを使用して、アップロードされた画像を処理(ここでは、幅と高さが最大500ピクセルになるようにリサイズ)することを指定しています。 -
extension_allowlist
: アップロードを許可するファイルの拡張子を定義しています。ここではjpg
、jpeg
、gif
、png
の4つの拡張子を持つファイルのみがアップロードを許可されています。 -
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
-
CarrierWave.configure do |config|
: CarrierWaveライブラリの設定を開始します。config
オブジェクトを使って、設定オプションを指定します。 -
config.fog_credentials
: ここでAmazon S3に接続するための認証情報を指定します。’AWS’はプロバイダとしてAmazonを指定していることを示しています。以下のaws_access_key_id
とaws_secret_access_key
は、S3にアクセスするために必要な認証キーです。region
はAWSのリージョンを指定します。ここでは ‘ap-northeast-1’(東京リージョン)が指定されています。 -
config.fog_directory = ENV["DIRECTORY_NAME"]
: アップロードされたファイルを保存するS3のバケット(ディレクトリ)名を設定します。 -
config.asset_host = ENV["ASSET_HOST"]
: ファイルへのURLが生成される際のベースURLを指定します。アセットホストが指定されると、生成されるURLはこのホストを基にします。 -
config.cache_storage = :fog
: アップロード前のキャッシュストレージとしてS3を使用することを指定します。これにより、アップロード前の一時的なファイルもS3上に保存されます。 -
config.fog_public = false
: ファイルへのアクセスを非公開にします。false
に設定すると、生成されるURLは署名付きURLとなり、一定時間経過後にアクセスできなくなります。 -
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 %>