限制每个用户上传到 AWS S3 的总大小 (MB)(使用 Shrine)

Limit total size (MBs) of uploads per user to AWS S3 (using Shrine)

我正在开发一个 Rails 应用程序,它允许用户通过 Shrine 将他们的图像上传到 AWS S3。到目前为止的设置工作得很好——但是,我想知道是否有任何直接提取每个用户上传的总大小的方法。

例如,我确实希望只允许免费用户上传最大 500MB,而会员只能上传 4GB。

没有在Github或Google上找到有用的东西,总的来说,也许有人可以分享他们的知识。干杯!

当前代码:

photo.rb

class Photo < ApplicationRecord
  include ImageUploader[:image]

  before_create :set_name

  belongs_to :employee
  belongs_to :user

  private

    def set_name
      self.name = "Photo"
    end
end

image_uploader.rb

require "image_processing/mini_magick"

class ImageUploader < Shrine
  include ImageProcessing::MiniMagick
  plugin :determine_mime_type
  plugin :remove_attachment
  plugin :store_dimensions
  plugin :validation_helpers
  plugin :pretty_location
  plugin :processing
  plugin :versions

  Attacher.validate do
    validate_max_size 5.megabytes, message: "is too large (max is 5 MB)"
    validate_mime_type_inclusion %w[image/jpeg image/png], message: " extension is invalid. Please upload JPEGs, JPGs and PNGs only."
    validate_min_width 400, message: " must have a minimum width of 400 pixel."
    validate_min_height 250, message: " must have a minimum height of 250 pixel."
  end

  process(:store) do |io, context|

    size_800 = resize_to_limit!(io.download, 800, 800)
    size_300 = resize_to_limit!(io.download, 300, 300)

    {original: io, large: size_800, small: size_300}
  end
end

所以这是我的解决方案 - 自定义验证器。非常基本,但我认为应该可以(未完全测试,需要赶飞机):

class Photo < ApplicationRecord
  include ImageUploader[:image]
  include ActiveModel::Validations

  before_create :set_name

  belongs_to :employee
  belongs_to :user

  validate :upload_size_validation

  private

    def set_name
      self.name = "Photo"
    end

    def upload_size_validation
      size = 0

      user.photos.each do |photo|
        byebug
        size = size + photo.image[:large].size.to_i
      end

      errors[:photo] << " cannot be uploaded as you hit the quota of 5 MB" if size > 50000
    end
end

如果有更好的解决办法,欢迎分享!

如果您想在照片模型的 image 列中添加验证错误消息,您可以在 Shrine 验证中执行此操作,因为您可以在那里访问照片记录。

class ImageUploader < Shrine
  # ...

  Attacher.validate do
    record #=> #<Photo ...>

    all_images = record.user.photos
      .select { |photo| photo.image_attacher.stored? }
      .map { |photo| photo.image[:large] }

    total_size = all_images.map(&:size).inject(0, :+)

    if total_size + get.size > 500.megabytes
      errors << "exceeds total maximum filesize for your account (max is 500MB)"
    end

    # ...
  end
end

首先,我们只过滤存在并上传到永久存储的附件(例如,如果您使用后台处理,会有一段时间只有缓存的文件被附加)。

然后我们将汇总 large 个版本的所有图像大小,如您的示例所示。

最后,我们将当前附件大小添加到总大小中,如果超过限制,我们将添加验证错误。