Reputation: 19505
I am using CarrierWave, and I would like to validate file names and only allow file uploads if the extension is .gif
, .png
, .jpg
, .jpeg
, or if there is no file extension.
Sometimes users upload files with no extensions. For example:
http://t2.gstatic.com/images?q=tbn:ANd9GcTCD2TLvYI8a4ChgBaYK_JaRfedvXLr3HXQfj0arXXAii3o2yjf
I am aware of the possibility of uncommenting the following lines in uploaders/image_uploader.rb
, but I don't know of a way of additionally saying "allow any of these extensions only if there is a file extension".
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
#def extension_white_list
# %w(gif jpg jpeg png)
#end
As well, in my model I have a validation as follows, but for some reason bad-extension.bad
passes.
validates :image, allow_blank: true, format: {
with: %r{\.(gif|jpe?g|png)\z}i,
message: 'must be a GIF, JPG, or PNG'
}, if: :filename_has_extension?
def filename_has_extension?
image =~ /\./
end
Upvotes: 7
Views: 4746
Reputation: 378
in my case I just change in my avatar_uploader.rb:
def extension_white_list
%w(jpg jpeg gif png) if model.avatar.file.extension.present?
end
:)
Upvotes: 0
Reputation: 5962
Well Why not use Mimetype comparison of the file in validation process there is ruby gem call mimetype that can help you in your quest
something like this
AVAILABLE_MIMETYPE = %w(image/gif)
validate :mime_type_of ,:if => :if_changed?
private
def mime_type_of
AVAILABLE::MIMETYPE.include?(MIME::Types.type_for[image_path][0])
end
def if_changed?
new_record? or image_changed?
end
Even CarrierWave Include MimeType Gem Internally check if that can help too
Hope this Help
Upvotes: 2
Reputation: 19505
image
is not a String
, rather it's of the class ImageUploader
(class ImageUploader < CarrierWave::Uploader::Base
).
Therefore this line is at fault:
image =~ /\./
Correct it by converting it to a String
:
image.to_s =~ /\./
That said, a better expression would be:
!(image.to_s =~ /\.[a-z]{1,4}\z/).nil?
It makes sure that the extension consists of one to four a-z
characters. Also, =~ returns nil
if nothing is found, and this line takes that into account.
If an extension is not found, =~
returns nil
; so .nil?
will return true
; and !
will invert it to false
; thus indicating that there is no extension.
If on the other hand there is an extension, =~
returns the position the match starts; which is 0
or greater, which is not nil
; so .nil?
will return false
; and when inverted by !
, true
is returned; thus indicating that there is an extension.
Upvotes: 0