2008-09-09 21 views
65

¿Cómo determina de manera confiable el tipo de archivo? El análisis de extensión de archivo no es aceptable. Debe haber una herramienta rubyesque similar al comando UNIX file (1)?Determine el tipo de archivo en Ruby

Esto se refiere a MIME o tipo de contenido, no a las clasificaciones del sistema de archivos, como el directorio, el archivo o el socket.

Respuesta

-2

Puede dar una oportunidad con MIME::Types for Ruby.

Esta biblioteca permite la identificación del tipo de contenido MIME probable de un archivo. La identificación del tipo de contenido MIME se basa en las extensiones de nombre de archivo de un archivo.

+6

de Readme.txt: "La identificación del tipo de contenido MIME se basa en las extensiones de nombre de archivo de un archivo". OP solicitó explícitamente un método basado en análisis de contenido, no extensión de nombre de archivo. –

33

Si estás en una máquina Unix intente esto:

mimetype = `file -Ib #{path}`.gsub(/\n/,"") 

No estoy al tanto de cualquier solución de rubíes puros que trabajan tan fiable como 'archivo'.

Editado para agregar: dependiendo del sistema operativo que esté ejecutando, es posible que deba utilizar 'i' en lugar de 'I' para que el archivo devuelva un tipo mime.

+16

Para evitar hackers desagradables, intente usar popen: 'IO.popen ([" file "," --brief "," --mime-type ", path], en:: close, err:: close) .read. chomp' – sj26

+0

Sí, esta o la gema 'cocaína'. – maletor

+6

@ sj26 Cada vez que llamo a 'popen', obtengo un proceso zombie porque el objeto IO no está cerrado. Para arreglar eso, use un bloque: 'IO.popen ([" file "," --brief "," --mime-type ", path], en:: close, err:: close) {| io | io.read.chomp} ' – Andrew

2

Puede probar shared-mime (instalación de gema shared-mime-info). Requiere el uso de la biblioteca de información de mimo compartida de Freedesktop, pero tanto las verificaciones de nombre de archivo/extensión como las verificaciones "mágicas" ... intenté darle un giro solo ahora, pero no tengo el freedesktop shared-mime-info la base de datos instalada y tiene que hacer un "trabajo real", desafortunadamente, pero podría ser lo que está buscando.

57

Hay un ruby ​​vinculante para libmagic que hace lo que necesita. Está disponible como una joya llamada ruby-filemagic:

gem install ruby-filemagic 

Requerir libmagic-dev.

La documentación parece un poco delgado, pero esto debe empezar:

$ irb 
irb(main):001:0> require 'filemagic' 
=> true 
irb(main):002:0> fm = FileMagic.new 
=> #<FileMagic:0x7fd4afb0> 
irb(main):003:0> fm.file('foo.zip') 
=> "Zip archive data, at least v2.0 to extract" 
irb(main):004:0> 
+0

De acuerdo con http://grub.ath.cx/filemagic/CHANGELOG esta joya no parece mantenerse activamente. –

+21

Me complace informar que esta gema una vez más se mantiene activamente https://github.com/blackwinter/ruby-filemagic –

+0

También funciona en Windows. –

-1

La gema rubí es así. mime-types for ruby

+0

Esta gema utiliza la extensión del archivo para determinar el tipo, no el contenido. –

+0

Gracias por su respuesta. Este método no es una buena idea. – Qianjigui

1

Encontré mimetype-fu recientemente.

Parece ser la solución más fácil y confiable para obtener el tipo MIME de un archivo.

La única advertencia es que en una máquina Windows solo utiliza la extensión de archivo, mientras que en los sistemas basados ​​en * Nix funciona muy bien.

12

Me pareció que desear ser el más confiable.Para la compatibilidad tanto en Mac OS X y Ubuntu Linux utilicé:

file --mime -b myvideo.mp4
video/mp4; charset = binaria

Ubuntu también imprime información de códec de vídeo si se puede, que está muy bien:

file -b myvideo.mp4
ISO Media, sistema v4 MPEG, versión 2

+5

debe ser 'file -b --mime-type myvideo.mp4' para uso web –

8

Puede utilizar esta base método fiable en la cabecera de la magia del archivo:

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 
4

Si está utilizando la clase de archivos, puede incrementarla con las siguientes funciones basadas en @ de PatrickRichie respuesta:

class File 
    def mime_type 
     `file --brief --mime-type #{self.path}`.strip 
    end 

    def charset 
     `file --brief --mime #{self.path}`.split(';').second.split('=').second.strip 
    end 
end 

Y, si está utilizando Ruby on Rails, puede colocarlo en config/initializers/file.rb y tenerlo disponible durante todo el proyecto.

Cuestiones relacionadas