Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 paperclip mime type - Office 2007

My rails app is having trouble identifying Office 2007 documents (pptx, xlsx, docx); it uploads via paperclip with the application/zip mime-type.

It also appears my system (OSX Lion) is detecting the file as a zip as well.

james@JM:~$  file --mime -b test.docx 
application/zip; charset=binary

I've tried adding the following to my initializers/mime_types

Rack::Mime::MIME_TYPES.merge!({
    ".docx"     => "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
})

But with no luck.

Any ideas?

like image 755
Jamsi Avatar asked Dec 28 '25 14:12

Jamsi


1 Answers

This is browser-dependent. The mime types are set as content type by the browser. This depends on the browser implementation and any possible client-side mime type settings that may exist on the client machine.

I've come to the conclusion that checking for document types isn't reliable via the mime type (i.e. content type) alone. It needs a mix of checking for mime type and file extension. File extension alone is also not that reliable, but the combination of both can probably be made to be reasonably workable.

Sadly, Paperclip out of the box doesn't seem to support validating by file extension, so custom code is needed. Here is what I came up with as a custom validation:

has_attached_file :file, ...

validate :mime_type_or_file_extension

private
def mime_type_or_file_extension
  if self.file.present? &&
     !VALID_UPLOAD_FILE_CONTENT_TYPES.include?(self.file_content_type) &&
     !VALID_UPLOAD_FILE_EXTENSIONS.include?(Pathname.new(self.file_file_name).extname[1..-1])
    self.errors.add(:file_file_name, "must be one of ." + VALID_UPLOAD_FILE_EXTENSIONS.join(' .'))
  end
end

Where VALID_UPLOAD_FILE_CONTENT_TYPES and VALID_UPLOAD_FILE_EXTENSIONS are two arrays we have defined in an initializer. Our attachment is called "file"

Perhaps something like this could be added to the Paperclip gem as pull request. I'll see if I find the time.

Update (12/23/2011) @Jamsi asked about download. We set the Content-Disposition and Content-Type in the response header in the controller, like so:

  response.headers['Content-Disposition'] = "attachment; filename=#{@upload.file_file_name}"
  response.headers['Content-Type'] = Rack::Mime.mime_type(File.extname(@upload.file_file_name))

Where @upload is our file (Paperclip) object.

like image 194
Wolfram Arnold Avatar answered Dec 31 '25 18:12

Wolfram Arnold



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!