【Rails 7】Amazon S3に画像登録する前にリサイズを行う(Gem libvips)
タイトルが入りきらなかったのでサブタイトルをここに書く(長いっ!)
ActiveStorageにてgem ActiveStorage Validationのvariantメソッドを使い
image_processing経由でlibvipsにて画像サイズの変換処理をする
使うやつは全部書いておかないとね。
環境
Mac OS
Docker
Ruby 3.3.6
Rails 7.2.2.1
Amazon S3に画像保存する前にリサイズして保存容量を抑えよう!!
登録から1年間AWS S3の無料利用枠があるとはいえ、使えるのは5GBまで。
そこからWebサービスで写真の枚数の登録がさらに増えていくとなると1MBでさえ抑えておきたい。
そこでRailsガイドのActiveStorage の概要より、ActiveStorageで、アプリケーションにアップロードした画像の変形を行っていきたいと思います。
1.1 要件をそのまま書くと
Active Storageの多くの機能は
Railsによってインストールされないサードパーティソフトウェアに依存しているため
別途インストールが必要です。
libvips v8.6以降(またはImageMagick): 画像解析や画像変形用
ffmpeg v3.4以降: 動画プレビュー、ffprobeによる動画/音声解析
popplerまたはmuPDF: PDFプレビュー用
画像分析や画像加工のためにimage_processing gemも必要です。
Gemfileのimage_processing gemをコメント解除するか、必要に応じて追加します。
gem "image_processing", ">= 1.2"
ImageMagickは、libvipsに比べて知名度が高く普及も進んでいます。
しかしlibvipsは10倍高速かつメモリ消費も1/10です。
JPEGファイルの場合、libjpeg-devをlibjpeg-turbo-devに置き換えると2〜7倍高速になります。
⚠️注意⚠️
サードパーティのソフトウェアをインストールして使う前に、
そのソフトウェアのライセンスを読んで理解しておきましょう。
特にMuPDFはAGPLでライセンスされており、利用目的によっては商用ライセンスが必要です。
主要となっているのはImagemagickらしいですが、
今回はあまり記事のないlibvipsを使ってやっていこうかなと思います。
さて。まず………なにすりゃいいんだ?w
毎回ながら迷走する自分…
・gem libvipsで調べたら出てきたけど、名前が「ruby-vips」……???
・libvipsとどう違うんだ?
・そもそもgem image_processingって何してるん?
etc...
ひとまず…
関係性としては
[Railsサーバ]---[ActiveStorage]---[image_processing]---[libvips]
image_processing:Railsで使うコードを翻訳(パイプライン)
libvips:画像処理(C言語)
どう投げるか?
- ユーザが画像アップロード
- ActiveStorageにて「variant(resize_to_limit: [300, 300])」というvariant設定で画像加工を指示
- image_processingにてlibvipsで使うC言語の命令「vips.resize(300, 300)」に翻訳
- libvipsが画像処理を行う(ImageMagick <mini_magick>も同様)
その他C言語だと。。。
C言語 = メモリ効率◎、処理速度◎
と言ったところかな…?
さてやっていこう… と思ったら先駆者が記事を書いていた
先駆者の記事はこちら↓
【Rails 7】Active Storage × Cloudinary で画像保存+libvipsで画像フォーマット
教えていただきありがとうございます(● ˃̶͈̀ロ˂̶͈́)੭ꠥ⁾⁾本当にありがたいっっ!!
参考にしながら書いていこうかな。
記載いただいている内容をやっていく。
実装
画像保存部分の設定
記載通りジェムをインストール。
ちなみにimage_processingをインストールするとmini_magickもインストールされています(gemfile lockを確認)

→ほんとだ!ruby-vipsも入ってる!(疑問に思ってたgemが一緒に入ってる)
必要なgemのインストールが終わったら、次はActiveStorageの有効化を行っていきます
ActiveStorageは有効済みなので、私は今回飛ばします。。。
画像用のバリデーションを追加
(コードコピペしてます)
class Post < ApplicationRecord
# 省略
has_one_attached :image # さっき追加したやつ
# ファイルの種類とサイズのバリデーション(gem ActiveStorage Validationを使用)
ACCEPTED_CONTENT_TYPES = %w[image/jpeg image/png image/gif image/webp].freeze
validates :image, content_type: ACCEPTED_CONTENT_TYPES,
size: { less_than_or_equal_to: 5.megabytes }
# 省略
end
- .freeze :
Rubyでオブジェクトを「凍結」するメソッドです。
簡単に言うと、そのオブジェクトを変更不可(イミュータブル)にするためのものです。
…なるほど。
jpeg、gif、webpに固定して、ACCEPTED_CONTENT_TYPESという引数に入れ、
画像のvalidate(登録条件)をその引数に入っている拡張子で、5Mバイトいかにしろってことか。
(あ。書いてた。<おいっ)
実際、Gemを使わなくてもいいらしいけど、このGemを使うことで
コードがスッキリするみたい。
class Spot < ApplicationRecord
has_one_attached :spot_image
validate :correct_image_type
private
def correct_image_type
return unless spot_image.attached?
acceptable_types = ["image/jpeg", "image/png", "image/jpg"]
unless acceptable_types.include?(spot_image.content_type)
errors.add(:spot_image, "はJPEGまたはPNG形式のみアップロード可能です")
end
end
end
Gemありの場合は以下の通り1行にまとめられます。ただこれは非推奨。
validates :spot_image, content_type: ['image/png', 'image/jpg', 'image/jpeg']
推奨は画像のタイプをビューファイルで使用できるようにするために
class User < ApplicationRecord
ACCEPTED_CONTENT_TYPES = ["image/jpeg", "image/png", "image/webp"].freeze
has_one_attached :avatar
validates :avatar, content_type: ACCEPTED_CONTENT_TYPES
end
他のファイルでファイル形式を決めるため引数に入れることで
ビューファイルにてその引数が使えるようになるみたい。
<%= form_with model: @user do |f| %>
<%= f.file_field :avatar,
accept: ACCEPTED_CONTENT_TYPES.join(',') %>
<% end %>
・・・そもそもwebpってなにっ?
| 端末 | 拡張子 | MIMEタイプ | 備考 |
|---|---|---|---|
| iPhone(カメラ) | .heic |
image/heic または image/heif
|
⚠️ iOS 11以降デフォルト |
| Android(カメラ) |
.jpg / .jpeg
|
image/jpeg |
✅ 標準的 |
| 一部のAndroid | .webp |
image/webp |
❗ 使用機種による |
| スクショ(iOS/Android) | .png |
image/png |
✅ 安定 |
| デジカメ |
.jpg / .jpeg
|
image/jpeg |
✅ 安定 |
→一部アンドロイドで使われる拡張子っぽい?
iPhoneの画像は基本的にクロームなどで使うとjpegに変えてくれるんだとか。
・・・スマホからPCに画像を飛ばしたらHEICのままだった気がするので、image/heic入れておこうかしら。
ひとまず疑問はここまでかな。
:imageをストロングパラメーターに追加
から
ここまで設定できればOK!
は飛ばします。が。
Amazon S3に画像保存するためには以下が必要。
今回はスキップします。やり方は軽く書きますが…これらは各自調べてみてください。
1. Gemのインストール(gem 'aws-sdk-s3')
2. config/storage.yml にS3設定を追加
3. config/environments/development.rb 等で保存先を指定(本番環境はproduction)
4. .env や credentials.yml.enc にAWSの認証情報を記載
5. バケット作成(AWS側)
6. アップロードがS3に反映されるか確認
その他参考にしたサイトも貼っておきます。
・Railsガイド v7.2_Active Storage の概要
・[Rails]Active Storageの画像をAWS S3へ保存する