Detect MIME type of uploaded file in Ruby

The ruby-filemagic gem will do it:

require 'filemagic'

# => text/x-ruby; charset=us-ascii

This gem does not look at the file extension at all. It reads a bit of the file contents and uses that to guess the file's type.

In Ruby on Rails you can do:

MIME::Types.type_for("filename.gif").first.content_type # => "image/gif"

The ruby-filemagic gem is good solution, but requires additional dependencies on libmagic (recently removed from CarrierWave as part of CarrierWave::MagicMimeTypes removal).

If you're interested in a pure ruby implementation, consider the MimeMagic gem! It works well for file types listed in the mime database:

require 'mimemagic'

MimeMagic.by_magic('Table-Flip-Guy.jpg')).type # => "image/jpeg" 

For Microsoft Office 2007+ formats (xlsx, docx, and pptx), require the overlay (unless you're okay with the generic "application/zip" MIME type for these files)

require 'mimemagic'    
require 'mimemagic/overlay'

MimeMagic.by_magic('big_spreadsheet.xlsx')).type # => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" 

You can use this reliable method base on the magic header of the file :

def get_image_extension(local_file_path)
  png ="\x89PNG".force_encoding("binary"))
  jpg ="\xff\xd8\xff\xe0\x00\x10JFIF".force_encoding("binary"))
  jpg2 ="\xff\xd8\xff\xe1(.*){2}Exif".force_encoding("binary"))
  case, 10)
  when /^GIF8/
  when /^#{png}/
  when /^#{jpg}/
  when /^#{jpg2}/
    mime_type = `file #{local_file_path} --mime-type`.gsub("\n", '') # Works on linux and mac
    raise UnprocessableEntity, "unknown file type" if !mime_type
    mime_type.split(':')[1].split('/')[1].gsub('x-', '').gsub(/jpeg/, 'jpg').gsub(/text/, 'txt').gsub(/x-/, '')