在Rails 4中验证文件扩展名

时间:2015-02-04 21:28:42

标签: ruby-on-rails ruby regex

我已经编写了一个自定义验证来检查文件扩展名,使用carrierwave(我知道这不会阻止文件被伪造)但是知道它就足够了。

但是我认为我没有得到它,或者至少我认为这可以被优化

class Document < ActiveRecord::Base
validate :file_format, :if => 'media?'
  def file_format
    filename = self.media.filename
      if filename !~ /.(png|PNG|jpg|JPG|jpeg|JPEG|mp4|MP4|docx|DOCX|pdf|PDF)/
       errors[:document] << "File format not supported"
      end
  end
end

正则表达式是否可以考虑不区分大小写(我相信使用i)?

当我上传文件时,请求只是挂起,但是当我重新加载页面时,文件就在那里。我认为我的验证方法存在问题。

3 个答案:

答案 0 :(得分:3)

您可以直接从CarrierWave Uploader类处理验证文件扩展名。

class MyUploader < CarrierWave::Uploader::Base
  def extension_white_list
    %w( jpg jpeg png pdf mp4 docx doc )
  end
end

如果您决定在包含模型中进行此验证,为什么甚至使用正则表达式?

class MyModel < ActiveRecord::Base
  validates :file_format, if: :media?

  def file_format
    unless valid_extension? self.media.filename
      errors[:document] << "Invalid file format."
    end
  end

  def valid_extension?(filename)
    ext = File.extname(filename)
    %w( jpg jpeg png pdf mp4 docx doc ).include? ext.downcase
  end
end

这更简单,读起来更容易,特别是因为您没有使用任何其他正则表达式功能。

答案 1 :(得分:1)

当然,//i是不区分大小写的正则表达式。

我还会在你的正则表达式的末尾添加\ Z,否则你会在其中的任何地方匹配文件,例如“PNG”,而不仅仅是在最后。

此外,你需要逃避.,或者它意味着“任何角色”,而不是句号。

/\.(png|PNG|jpg|JPG|jpeg|JPEG|mp4|MP4|docx|DOCX|pdf|PDF)\Z/

此外,您确定要根据文件名进行验证,而不是基于MIME类型验证,还是两者兼而有之?

我认为你的悬挂问题可能不是由于你的验证,而是由于载波集成的其他方面。但是有一个简单的方法可以找到,关闭验证,看看悬挂问题是否仍然存在。

答案 2 :(得分:0)

这个问题已经有一段时间了,因此这是Rails v4创建自定义验证器(app/validators/file_validator.rb)的有效示例:

class FileValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)
    if value
      if value.respond_to? :path
        unless options[:ext].include? File.extname(value.original_filename).delete('.').to_sym
          record.errors[attribute] << " is not a valid file (#{options[:ext].join(',')})"
        end
      else
        record.errors[attribute] << (options[:message] || 'is not a file')
      end
    end
  end

end

用法示例(用户模型):

class User < ActiveRecord::Base

  attr_accessor :avatar_file

  # other validators ...
  
  # Avatar validation
  validates :avatar_file, file: {ext: [:jpg, :png]}

  # logic...

end

这个简单的验证器检查图像扩展名(jpg,png)。