Determining Image File Types in Ruby

Today I came across a PNG file that had been uploaded from a browser with a .JPG extension and image/jpeg MIME type. It’s too bad that MIME types are apparently unreliable when it comes to file uploads. I went looking for a way to determine the file type by actually reading the file. This is probably a solved problem, but I was unsuccessful Googling for the answer. I came up with the following Ruby method which decides the image file type using up to the first 10 bytes:

def image_type(file)
  case IO.read(file, 10)
    when /^GIF8/: ‘gif’
    when /^\x89PNG/: 'png’
    when /^\xff\xd8\xff\xe0\x00\x10JFIF/: 'jpg’
    when /^\xff\xd8\xff\xe1(.*){2}Exif/: 'jpg’
  else 'unknown’
  end
end

This works well on a small set of test files (400+ from a browser temp files directory). Let me know if there’s a case where this code doesn’t work, or if there’s a better solution in general.

Update: This idea was expanded and found its way into a gem: ruby-imagespec. Credit for that goes to Brandon Anderson, Michael Sheakoski, and Dimitrij Denissenko.