web-dev-qa-db-fra.com

Détecter le type MIME du fichier téléchargé dans Ruby

Existe-t-il un moyen à toute épreuve de détecter le type MIME de fichier téléchargé dans Ruby ou Ruby on Rails? Je télécharge des fichiers JPEG et PNG à l'aide de SWFupload et content_type est toujours "application/octet-stream"

43
Vincent

Le Ruby-filemagic gem le fera:

require 'filemagic'

puts FileMagic.new(FileMagic::MAGIC_MIME).file(__FILE__)
# => text/x-Ruby; charset=us-ascii

Cette gemme ne regarde pas du tout l'extension du fichier. Il lit un peu du contenu du fichier et l'utilise pour deviner le type du fichier.

47
Wayne Conrad

Dans Ruby on Rails vous pouvez faire:

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

Vous pouvez utiliser cette base de méthode fiable sur l'en-tête magique du fichier:

def get_image_extension(local_file_path)
  png = Regexp.new("\x89PNG".force_encoding("binary"))
  jpg = Regexp.new("\xff\xd8\xff\xe0\x00\x10JFIF".force_encoding("binary"))
  jpg2 = Regexp.new("\xff\xd8\xff\xe1(.*){2}Exif".force_encoding("binary"))
  case IO.read(local_file_path, 10)
  when /^GIF8/
    'gif'
  when /^#{png}/
    'png'
  when /^#{jpg}/
    'jpg'
  when /^#{jpg2}/
    'jpg'
  else
    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-/, '')
  end  
end
21
Alain Beauvois

La gemme Ruby-filemagic est une bonne solution, mais nécessite des dépendances supplémentaires sur libmagic (récemment supprimé de CarrierWave dans le cadre de Suppression de CarrierWave :: MagicMimeTypes ).

Si vous êtes intéressé par une pure implémentation Ruby, considérez la gemme MimeMagic ! Cela fonctionne bien pour les types de fichiers répertoriés dans la base de données mime freedesktop.org:

require 'mimemagic'

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

Pour les formats Microsoft Office 2007+ (xlsx, docx et pptx), exigez la superposition (sauf si vous êtes d'accord avec le type MIME générique "application/Zip" pour ces fichiers)

require 'mimemagic'    
require 'mimemagic/overlay'

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

filemagic gem est une bonne solution mais dépend de beaucoup de gemmes inutiles. (Rails, aws-sdk-core, ...)

Si votre application est petite et ne fonctionne que sous Linux ou OSX, pensez à utiliser le programme file:

require 'shellwords'
mimetype = `file --brief --mime-type - < #{Shellwords.shellescape(__FILE__)}`.strip

Remarque: remplacez __FILE__ avec tout expr contient le chemin du fichier.

6
kaorukobo

bijou mimémagique le fera aussi

https://github.com/minad/mimemagic

de la documentation officielle

MimeMagic est une bibliothèque pour détecter le type mime d'un fichier par extension ou par contenu. Il utilise la base de données mime fournie par freedesktop.org (voir http://freedesktop.org/wiki/Software/shared-mime-info/ ).

require 'mimemagic'
MimeMagic.by_extension('html').text?
MimeMagic.by_extension('.html').child_of? 'text/plain'
MimeMagic.by_path('filename.txt')
MimeMagic.by_magic(File.open('test.html'))
# etc...
4
priki