在CarrierWave上传器中验证图像大小

21

所有上传的图片应至少为150x150像素。如何使用Carrierwave进行验证?

4个回答

20

为什么不使用MiniMagick? 修改DelPiero的答案:

validate :validate_minimum_image_size

def validate_minimum_image_size
  image = MiniMagick::Image.open(picture.path)
  unless image[:width] > 400 && image[:height] > 400
    errors.add :image, "should be 400x400px minimum!" 
  end
end

酷!你的方法真的更好。 - Kir
1
@skalee,我收到了以下错误信息:PhotosController#create中的Errno::ENOENT 没有这样的文件或目录 - ,为什么会这样? - Gibson
我认为代码有错误。如果你的图片属性是 :picture,那么你应该将错误添加到 :picture 属性,而不是 :image - Anwar

14

我根据@skalee的回答,制作了一个稍微更完整的验证器。

class ImageSizeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value.blank?

      image = MiniMagick::Image.open(value.path)
      checks = [
        { :option => :width, 
          :field => :width, 
          :function => :'==',
          :message =>"Image width must be %d px."},
        { :option => :height, 
          :field => :height, 
          :function => :'==',
          :message =>"Image height must be %d px."},
        { :option => :max_width, 
          :field => :width, 
          :function => :'<=',
          :message =>"Image width must be at most %d px."},
        { :option => :max_height, 
          :field => :height, 
          :function => :'<=',
          :message =>"Image height must be at most %d px."},
        { :option => :min_width, 
          :field => :width, 
          :function => :'>=',
          :message =>"Image width must be at least %d px."},
        { :option => :min_height, 
          :field => :height, 
          :function => :'>=',
          :message =>"Image height must be at least %d px."},
      ]

      checks.each do |p|
        if options.has_key?(p[:option]) and 
          !image[p[:field]].send(p[:function], options[p[:option]])

          record.errors[attribute] << p[:message] % options[p[:option]]
        end
      end

    end
  end
end

请像这样使用 validates :image, :image_size => {:min_width=>400, :min_height=> 400}


非常有帮助!一个“安全研究员”刚刚对我进行了JPEG轰炸,我并不想费力去学习如何自己编写这个验证器 :) - Ryan Angilly
顺便说一句,如果有人想知道的话,这在 Mongoid 4 上完全正常运行。 - Ryan Angilly

8

让我惊讶的是,寻找一种简单明了的方法来验证CarrierWave中图像的宽度和高度是多么困难。@Kir上面的解决方案是正确的,但我想进一步解释他所做的事情,以及我进行的小修改。

如果您查看他的gist https://gist.github.com/1239078,答案就在Uploader类中的before :cache回调函数中。神奇的代码行是

model.avatar_upload_width, model.avatar_upload_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }

在这种情况下,avatar_upload_width和avatar_upload_height是他的用户模型的属性。我不想在数据库中存储width和height,因此在我的模型中,我这样说:

attr_accessor :image_width, :image_height

记住,你可以使用attr_accessor为那些你想在处理记录时随时拥有的属性,但不想将它们持久化到数据库中。所以我的神奇代码行实际上变成了:

model.image_width, model.image_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }

现在,我已经将图像的宽度和高度存储在模型对象中。最后一步是编写自定义验证维度的代码,在您的模型中需要添加类似以下内容:

validate :validate_minimum_image_size

然后在其下方定义您的自定义验证方法,与gist中相同

# custom validation for image width & height minimum dimensions
def validate_minimum_image_size
    if self.image_width < 400 && self.image_height < 400
        errors.add :image, "should be 400x400px minimum!" 
    end
end

谢谢您如此深入的解释! - Kir
2
我很感激能够找到你的代码示例,这个看似常见的操作却缺乏文档资料,真是太疯狂了! - DelPiero

7

我刚刚制作了一个自定义验证器,旨在更符合Rails 4+的语法。
我从这个话题中的其他回复中借鉴了一些想法。
以下是要点:https://gist.github.com/lou/2881f1aa183078687f1e

你可以像这样使用它:

validates :image, image_size: { width: { min: 1024 }, height: { in: 200..500 } }

在这种情况下,应该是:
validates :image, image_size: { width: 150, height: 150 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接