因此,在阅读官方文档后,我正在以这种方式使用Active Storage变体
<%= image_tag user.avatar.variant(resize: "100x100") %>
问题是,当我查看我的S3存储时,我注意到我有原始文件(例如大小为22kb)和包含2kb文件(调整大小的文件)的变体文件。
我在文档中说:
..“当浏览器访问变体URL时,Active Storage将懒惰地将原始blob转换为指定格式并重定向到其新服务位置。”
但有没有办法阻止Active Storage生成其他变体文件?就像制作变体一样,原始。因此,在S3中,我只有2kb而不是24kb的resurces。
非常感谢!
编辑:
我设法解决了应用一些答案的问题,如果有人遇到这个问题:
def resize_avatar2
avatar_f = avatar.last
if avatar_f.nil?
return
end
resized_image = MiniMagick::Image.read(avatar_f.download)
resized_image = resize_with_crop(resized_image, 300, 300)
v_filename = avatar_f.filename
v_content_type = avatar_f.content_type
avatar.all.each { |imagen| imagen.purge }
avatar.attach(
io: File.open(resized_image.path),
filename: v_filename,
content_type: v_content_type)
end
创建一个帮助器,使用以下方法包含它:
def resize_with_nocrop(image, w, h)
w_original = image[:width].to_f
h_original = image[:height].to_f
if (w_original*h != h_original * w)
if w_original*h >= h_original * w
# long width
w_result = w
h_result = w_result * (h_original / w_original)
elsif w_original*h <= h_original * w
# long height
h_result = h
w_result = h_result * (w_original / h_original)
end
else
# good proportions
h_result = h
w_result = w
end
#
image.resize("#{w_result}x#{h_result}")
return image
end
def resize_with_crop(img, w, h, options = {})
gravity = options[:gravity] || :center
w_original, h_original = [img[:width].to_f, img[:height].to_f]
op_resize = ''
# check proportions
if w_original * h < h_original * w
op_resize = "#{w.to_i}x"
w_result = w
h_result = (h_original * w / w_original)
else
op_resize = "x#{h.to_i}"
w_result = (w_original * h / h_original)
h_result = h
end
w_offset, h_offset = crop_offsets_by_gravity(gravity, [w_result, h_result], [ w, h])
img.combine_options do |i|
i.resize(op_resize)
i.gravity(gravity)
i.crop "#{w.to_i}x#{h.to_i}+#{w_offset}+#{h_offset}!"
end
img
end
GRAVITY_TYPES = [ :north_west, :north, :north_east, :east, :south_east, :south, :south_west, :west, :center ]
def crop_offsets_by_gravity(gravity, original_dimensions, cropped_dimensions)
raise(ArgumentError, "Gravity must be one of #{GRAVITY_TYPES.inspect}") unless GRAVITY_TYPES.include?(gravity.to_sym)
raise(ArgumentError, "Original dimensions must be supplied as a [ width, height ] array") unless original_dimensions.kind_of?(Enumerable) && original_dimensions.size == 2
raise(ArgumentError, "Cropped dimensions must be supplied as a [ width, height ] array") unless cropped_dimensions.kind_of?(Enumerable) && cropped_dimensions.size == 2
original_width, original_height = original_dimensions
cropped_width, cropped_height = cropped_dimensions
vertical_offset = case gravity
when :north_west, :north, :north_east then 0
when :center, :east, :west then [ ((original_height - cropped_height) / 2.0).to_i, 0 ].min
when :south_west, :south, :south_east then (original_height - cropped_height).to_i
end
horizontal_offset = case gravity
when :north_west, :west, :south_west then 0
when :center, :north, :south then [ ((original_width - cropped_width) / 2.0).to_i, 0 ].min
when :north_east, :east, :south_east then (original_width - cropped_width).to_i
end
return [ horizontal_offset, vertical_offset ]
end
如果您想用变体替换原件,我认为最好的方法是在图像上传之前调整图像大小。
例如使用params[:user][:avatar]
查找临时文件的路径,在其上运行ffmpeg(有宝石),然后上传结果。
或者,您可以在上传后对作业中的图像进行处理:
User
),添加一个after_create :resize_image
resize_image
的ImagesJob.resize(self).perform_later
方法resize(user)
方法)中,您将:
生成变体:url = user.avatar.variant(resize: "100x100").url
(Rails生成的URL,而不是S3的URL)
获取图像:image = open(url).read
(需要require 'open-uri'
)
找到变体的S3 URL,删除它,找到原始图像URL,删除它(你需要经过ActiveStorage::Blob
(active_storage_blobs
表)。
上传image
作为新图片user.avatar.attach(StringIO.new(image)); user.save
(未测试但可能非常接近)