How to resize images before uploading with Active Storage (linked with AWS)

问题描述 投票:0回答:4

我尝试将 Active Storage 与 Amazon Web Services 一起使用,而不是 Carrierwave 和 Cloudinary。

使用 Carrierwave,我有一些功能允许在通过 UploaderController 上传之前调整图像大小。

但是如何使用 Active Storage 做到这一点?

我试试这个:

宝石文件:

gem 'aws-sdk-s3', require: false
gem 'image_processing', '~> 1.2'
gem 'mini_magick', '~>4.9'

item.rb

class Item < ApplicationRecord
    has_one_attached :photo
end

我有一个表格:

<%= f.input :photo, input_html: { accept: ('image') } %>

我得到这个对象作为照片:

#<ActiveStorage::Attached::One:0x00005641d296e1b8 @name="photo", @record=#<Item id: nil, name: "test0941", verbe: "To Lend", collection_id: nil, created_at: nil, updated_at: nil, price_cents: 0, description: "", category_id: 78, photo: nil>, @dependent=:purge_later>

在我的控制器中:

@item = Item.new(item_params)
@item.photo.combine_options do |b|
    b.resize "250x200>"
end

我无法通过 MiniMagick gem 的方法调整我的照片大小

有人有什么想法吗?

感谢您的帮助, 蒂博

amazon-s3 rails-activestorage minimagick
4个回答
10
投票

如果 params[:item][:photo] 是您帖子中的参数,您可以添加

image = MiniMagick::Image.new(params[:item][:photo].tempfile.path)
image.resize "250x200>"

使用 ImageProcessing::Vips(Rails 7 中的默认设置)

path = params[:game][:photo].tempfile.path
image = ImageProcessing::Vips.source(path)
result = image.resize_to_limit!(800, 800)
params[:game][:photo].tempfile = result

1
投票

我是这样做的:

# config/initializers/activestorage.rb

# Ability to auto apply :default variant (if defined) before uploading original image
Rails.application.config.after_initialize do
  ActiveStorage::Blob.class_eval do
    alias_method :upload_without_unfurling_orig, :upload_without_unfurling
    
    def upload_without_unfurling(io)
      variant = attachments.first.send(:variants)
      default_variant = variant[:default]
      if default_variant
        ActiveStorage::Variation.wrap(default_variant).transform(io) do |output|
          unfurl output, identify: identify
          upload_without_unfurling_orig(output)
        end
      else
        upload_without_unfurling_orig(io)
      end
    end
  end
end

# user.rb
class User < ApplicationRecord
  has_one_attached :photo do |attachable|
    attachable.variant :thumb, resize_to_fill: [100, nil]
    # This variant will be applied before uploading the original image
    attachable.variant :default, strip: true, quality: 70, resize_to_fill: [500, 500]
  end
end

# rspec
RSpec.describe User, type: :model do
  describe 'when uploading photo' do
    it 'applies :default variant before uploading the original image' do
      allow(ActiveStorage::Variation).to receive(:wrap).and_call_original
      create(:user, :with_photo)
      exp_args = hash_including(resize_to_fill: [500, 500])
      expect(ActiveStorage::Variation).to have_received(:wrap).with(exp_args)
    end
  end
end

0
投票

将此作为

private
方法添加到您的控制器:

def resize_before_save(image_param, width, height)
  return unless image_param

  begin
    ImageProcessing::MiniMagick
      .source(image_param)
      .resize_to_fit(width, height)
      .call(destination: image_param.tempfile.path)
  rescue StandardError => _e
    # Do nothing. If this is catching, it probably means the
    # file type is incorrect, which can be caught later by
    # model validations.
  end
end

然后从控制器中的

before_action
调用它。

before_action lambda {
  resize_before_save(item_params[:picture], 250, 250)
}, only: [:create, :update]


-4
投票

主动存储可以解决您的问题。 您不需要在控制器中调整图像大小。您可以将其用作 item.photo.variant(resize: '100x100') 在您的视图文件中。 Active Storage 将像魔法一样创建新的变体图像。

这里是主动存储的文档。

https://edgeguides.rubyonrails.org/active_storage_overview.html

© www.soinside.com 2019 - 2024. All rights reserved.