musaffa / file_validators

Adds file validators to ActiveModel.
MIT License
260 stars 25 forks source link

Not validate content_type properly when use carrierwave-aws #5

Open robinbortlik opened 9 years ago

robinbortlik commented 9 years ago

Hi,

we use in our application carrierwave-aws gem for storing files to S3. And we also use the file_validators gem for validating content_type of uploaded file.

What happen is that when we assign file (for example pdf file and we check that content_type is 'application/pdf'). The record is valid and we can store it. But when we load the record from database and it load file from S3, then record is invalid. The file behave like 'application/octstream' instead of 'application/pdf' . But if I ask for record.content_type => 'application/pdf'

So I think the problem is on this line https://github.com/musaffa/file_validators/blob/master/lib/file_validators/validators/file_content_type_validator.rb#L59

If there happen any error with content_type detection it as default return 'application/octstream' .

If you can give me an idea, how to fix it, I will do it.

Thanks a lot.

musaffa commented 9 years ago

@robinbortlik I'm also having this problem with the remote file repository like S3. Currently the content type file validator cannot guess the file as the file is wrapped on a different object when it is fetched from a remote repository. I'll try to solve this issue. As a workaround for now, you can use carrierwave's filemagic integration

robinbortlik commented 9 years ago

Finally I went for custom solution. I implemented simple content_type validator like this

class ContentTypeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.present? && !allowed_content_types.include?(value.content_type)
      record.errors.add(attribute, :invalid)
    end
  end

  private
  def allowed_content_types
    options[:allow].to_a
  end
end

and used it in model

validates :file, content_type: { allow: ['application/pdf'] }

And it works quite well :)

musaffa commented 9 years ago

Yes it should :p . But not quite secure though. I will keep this issue open until it is solved.

xpepermint commented 8 years ago

+1, my workaround is

validates :video, file_size: { less_than_or_equal_to: 50.megabytes, if: ->(a){ a.video_changed? } }
ollieh-m commented 7 years ago

I was having a similar issue where images in S3 were being identified by the file_content_type_validator as of type application/octstream. I found that when the validator deferred to value.content_type, the type was application/octstream, but when I passed a mode into the validation (i.e. allow: ['image/jpeg'], mode: :relaxed), the type was correctly identified. Basically this worked but this didn't. I'm not sure why, but others who find their way to this issue might find joy adding mode: :relaxed or mode: :strict to their validation.