Carrierwave sets mime type to invalid/invalid

Viewed 607

I recently upgraded from Carrierwave 1.3 to 2.1, and I got a couple of specs failing due to the invalid mime type.

I store on the database, CSV Uploads, and I validate on the model if the mime type is text/csv.

validates :file, presence: true, file_content_type: {
    allow: [
      'text/csv',
      'application/vnd.ms-excel',
      'application/vnd.ms-office',
      'application/octet-stream',
      'text/comma-separated-values'
    ]
  }

and on the spec, I created a fixture

let(:file) { fixture_file_upload('files/fixture.csv', 'text/csv') }

when I debug,

@file=
  #<CarrierWave::SanitizedFile:0x00007f8c731791f0
   @content=nil,
   @content_type="invalid/invalid",
   @file="/Users/tiagovieira/code/work/tpc/public/uploads/csv_file_upload/file/1/1605532759-308056149220914-0040-7268/fixture.csv",
   @original_filename="fixture.csv">,
 @filename="fixture.csv",
 @identifier="fixture.csv",

Is this related to the fact that carrierwave stopped using mime-types gem as a dependency?

2 Answers

Seems the problem is found.

In previous carrierwave version "CarrierWave::SanitizedFile" content_type was calculated by extension https://github.com/carrierwaveuploader/carrierwave/blob/1.x-stable/lib/carrierwave/sanitized_file.rb

    def content_type
      return @content_type if @content_type
      if @file.respond_to?(:content_type) and @file.content_type
        @content_type = @file.content_type.to_s.chomp
      elsif path
        @content_type = ::MIME::Types.type_for(path).first.to_s
      end
    end

And now it has more complicated way. It uses algorithms to recognize the file type by what data this file contains.

https://github.com/carrierwaveuploader/carrierwave/blob/master/lib/carrierwave/sanitized_file.rb

    def content_type
      @content_type ||=
        existing_content_type ||
        mime_magic_content_type ||
        mini_mime_content_type
    end

And i have "invalid/invalid" content-type after mime_magic_content_type which seems could not fetch file type using "MimeMagic.by_magic".

PS i see that "plain/text" content_type is returned for usual css file. https://github.com/minad/mimemagic/blob/master/lib/mimemagic/tables.rb#L1506

use Rack::Test::UploadedFile

assign the mounted model a Rack::Test::UploadedFile object assume your model is:

class User < ApplicationRecord
  mount_uploader :file, FileUploader
end

to test the uploader you can use something like:

user.file = Rack::Test::UploadedFile.new(File.open('test_file.csv'), "text/csv")
user.save

whitelist by Carrierwave's content_type_whitelist or extension_whitelist

class FileUploader < CarrierWave::Uploader::Base

  private

  def extension_whitelist
    %w(csv xlsx xls)
  end

  def content_type_whitelist
    [
      'text/csv',
      'application/vnd.ms-excel',
      'application/vnd.ms-office',
      'application/octet-stream',
      'text/comma-separated-values'
    ]
  end
end

also check: https://til.codes/testing-carrierwave-file-uploads-with-rspec-and-factorygirl/

Related