class PostThumbnailUploadValidator MAX_THUMBNAIL_BYTES = 20 * 1024 * 1024 ALLOWED_CONTENT_TYPES = Preview::ThumbnailFetcher::ALLOWED_IMAGE_CONTENT_TYPES.freeze class InvalidUpload < StandardError; end def self.validate! thumbnail return if thumbnail.blank? raise InvalidUpload, 'thumbnail upload が不正です.' unless thumbnail.is_a?(ActionDispatch::Http::UploadedFile) raise InvalidUpload, 'thumbnail file size が大きすぎます.' if thumbnail.size > MAX_THUMBNAIL_BYTES raise InvalidUpload, 'サムネイル画像の形式が不正です.' unless allowed_content_type?(thumbnail.content_type) attachment = Post.resized_thumbnail_attachment(thumbnail) attachment[:io].close if attachment[:io].respond_to?(:close) rescue MiniMagick::Error raise InvalidUpload, 'サムネイル画像の変換に失敗しました.' ensure thumbnail&.rewind if thumbnail.respond_to?(:rewind) end def self.allowed_content_type? content_type mime_type = content_type.to_s.split(';', 2).first.to_s.downcase.strip ALLOWED_CONTENT_TYPES.include?(mime_type) end end