我已经编写了一个自定义验证来检查文件扩展名,使用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
)?
当我上传文件时,请求只是挂起,但是当我重新加载页面时,文件就在那里。我认为我的验证方法存在问题。
答案 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)。