13

I am using paperclip gem to upload files. and my paperclip gem version is paperclip-4.1.1. While uploading a file its throwing

Validation failed: Upload file has an extension that does not match its contents.

I am trying to upload a xlsx file. and also i have mentioned that into the model content_type.

 validates_attachment_content_type :upload_file, :content_type => %w(application/msword application/vnd.ms-office application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet),
                                               :message => ', Only XML,EXCEL files are allowed. '

I don't know why this error is happening. If you have any idea about this error please share.

Excerpt from log to show validation failure:

Command :: file -b --mime-type '/tmp/5249540099071db4e41e119388e9dd6220140513-24023-1jlg4zy' [paperclip] Content Type Spoof: Filename file_for_bulk_upload1.xlsx (["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]), content type discovered from file command: . See documentation to allow this combination. 
Command :: file -b --mime-type '/tmp/6f19a4f96154ef7ce65db1d585abdb2820140513-24023-tt4u1e' [paperclip] Content Type Spoof: Filename file_for_bulk_upload1.xlsx (["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]), content type discovered from file command:
Can Can
  • 3,644
  • 5
  • 32
  • 56
  • Could you include the error from your log file please. Also, although it's not the cause of the failure, from the error message you seems to want to allow only xml or excel files. Why are you permitting word files to be loaded? THe MIME type for xml files is `application/xml` –  May 13 '14 at 11:41
  • Command :: file -b --mime-type '/tmp/5249540099071db4e41e119388e9dd6220140513-24023-1jlg4zy' [paperclip] Content Type Spoof: Filename file_for_bulk_upload1.xlsx (["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]), content type discovered from file command: . See documentation to allow this combination. Command :: file -b --mime-type '/tmp/6f19a4f96154ef7ce65db1d585abdb2820140513-24023-tt4u1e' [paperclip] Content Type Spoof: Filename file_for_bulk_upload1.xlsx (["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]), content type discovered from file command: – Can Can May 13 '14 at 11:44
  • Please could you manually check this file. At your unix prompt enter a couple of commands: `file --mime-type ` and `mimetype ` –  May 13 '14 at 11:46
  • file_for_bulk_upload1.xlsx: application/zip – Can Can May 13 '14 at 11:48
  • file_for_bulk_upload1.xlsx: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet – Can Can May 13 '14 at 11:49
  • @GraemeMcLean its working in my local machine. error is in test server. what could be the problem? – Can Can May 13 '14 at 11:51

3 Answers3

16

The Paperclip spoofing validation checks are failing because the file command is not able to accurately determine the filetype.

In your log content type discovered from file command: . - the blank space before the period is the result of the output - i.e. blank. However the other side of the comparison uses purely the file extension which is being correctly picked up as an excel file. Hence your validation failure.

The current version of Paperclip is using file -b --mime-type to determine the file, however --mime-type is not supported by all implementations. There is a change to use --mime instead but it's not in a milestone yet.

I think you have a some options. Which you choose depends on how concerned you are about some dodgy file being uploaded and being called an excel file. If you are worried about this then try option 1; if you are not worried go for option 2 or 3.

1) Override the spoofing check to use --mime instead of --mime-type.

Override the type_from_file_command in an initializer:

module Paperclip
  class MediaTypeSpoofDetector
    private

    def type_from_file_command
      # -- original code removed --
      # begin
      #   Paperclip.run("file", "-b --mime-type :file", :file => @file.path)
      # rescue Cocaine::CommandLineError
      #   ""
      # end

      # -- new code follows --
      begin
         Paperclip.run("file", "-b --mime :file", :file => @file.path)
      rescue Cocaine::CommandLineError
        ""
      end
    end
  end
end

2) Bypass the file check by setting the file type totally from it's file extension.

Set this Paperclip option somewhere that is read during initialisation of the application (e.g. config/application.rb, config/environments/<environment>.rb or an config/initializers/paperclip.rb):

Paperclip.options[:content_type_mappings] = { xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }

3) Disable spoofing altogether.

Override the spoofing check by creating something like this in an initializer:

module Paperclip
  class MediaTypeSpoofDetector
    def spoofed?
      false
    end
  end
end

Update:

The validation you have in your model is not the cause of this problem. This validates which types of files you are allowed to load; what you are seeing is Paperclip calculating that the type of the file is valid but its content do not match the type of the file.

Assuming you can get the spoofing validation to work, there is one anomaly with your content validation. The error message you output says "only XML, EXCEL files are allowed", however your actual validation is checking for MS word and excel files, not xml.

If your message is correct and you do want to allow only xml and excel files you should change the content_type validation to be:

validates_attachment_content_type :upload_file, :content_type => %w(application/xml application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet),
                                                :message => ', Only XML,EXCEL files are allowed. '
  • if i try the command mimetype file_for_bulk_upload1.xlsx in my testing server its returning -bash: mimetype: command not found – Can Can May 13 '14 at 12:18
  • Sorry, I thought you ran the `mimetype` command above on your test server. No matter, you can either install it with `sudo apt-get install libfile-mimeinfo-perl` or use one of the other options I provided if you can't get mimetype installed. *** actually, can you do `file --mime-type` on your test server? could this just be a permissions problem? –  May 13 '14 at 12:25
  • its giving file: unrecognized option `--mime-type' – Can Can May 13 '14 at 12:28
  • its giving file_for_bulk_upload1.xlsx: application/x-zip – Can Can May 13 '14 at 12:32
  • I have changed option 1 in my answer as it seems your implementation of `file` doesn't support `--mime-type`. This should work - however - given it is adament you `.xlsx` file is a zip file, it could actually be a genuine spoofing detection. Is your file zipped? If not, then you are going to have to go for option 2 or 3 as it seems you cannot reliably so spoofing detection on this server. –  May 13 '14 at 12:38
  • i tried option two. i added that file in production.rb. but its not working – Can Can May 13 '14 at 12:41
  • Options 1 and 2 didn't worked for me, so switched from `content_type` to just `file_name` validation. `validates_attachment :file, presence: true, file_name: {matches: [/xlsx\Z/]}`. That's ability for spoofing but only in that place - other image/video uploads still checked. Btw, it's time to migrate from paperclip to ActiveStorage – shooma Nov 13 '21 at 20:22
0

Faced similar problems tonight on upgrading from 4.2 to 5.3.

Options 1 and 2 from accepted answer didn't worked for me, so I switched from content_type to just file_name validation.

validates_attachment :file, presence: true, file_name: {matches: [/xlsx\Z/]}

Spoofing available but only for concrete attachment - other image/video uploads still checked.

PS: Anyway, paperclip is deprecated and it's time to migrate to ActiveStorage

shooma
  • 435
  • 6
  • 8
-1

try this way

validates_attachment_content_type :upload_file, :content_type => ["application/msword", "application/vnd.ms-office application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"], :message => ', Only XML,EXCEL files are allowed. '
Antony Mithun
  • 161
  • 1
  • 15
  • Is there any other change in your snippet except introducing double quotes and commas within %w()? By the way the whole purpose of %w() is to get rid of the quotes and the commas when you build an array. Try your snippet to see the resulting array with escaped quotes! – Kostas Rousis May 13 '14 at 11:39
  • `%w("a,b")` is not valid.It is incorrect.`%w(a b)` is valid. – Pavan May 13 '14 at 11:40
  • 3
    Your edited answer now provides a correct array which does not differ from OP's – Kostas Rousis May 13 '14 at 11:45
  • 1
    `%w(a b) = ["a,b"]`.Your answer is same as the Op's – Pavan May 13 '14 at 11:45