2010-02-08 11 views
15

Come verificherebbe se un file è un'immagine? Sto pensando che potresti utilizzare un metodo come questo:Ruby on Rails: come controllate se un file è un'immagine?

def image?(file) 
    file.to_s.include?(".gif") or file.to_s.include?(".png") or file.to_s.include?(".jpg") 
end 

Ma potrebbe essere un po 'inefficiente e non corretto. Qualche idea?

(sto usando il plugin graffetta, btw, ma non vedo alcun metodo per determinare se un file è un'immagine in graffetta)

risposta

12

userei la gemma ruby-filemagic che è vincolante per Ruby libmagic.

+0

Grazie a Sinan per l'ottimo collegamento! Non sapevo che esistesse. Grazie. – sjsc

+0

Il comando file è davvero ottimo per questo, quindi questo wrapper dovrebbe fare il lavoro. – tadman

1

imagemagick ha un comando chiamato identity che gestisce questo - controlla la documentazione di paperclip - c'è probabilmente un modo per gestirlo dall'app RoR.

+0

Grazie per la punta Claude e John sull'identità. Avrò un assegno. Grazie mille per il rinvio. – sjsc

7

Poiché si utilizza Paperclip, è possibile utilizzare il metodo integrato "validates_attachment_content_type" nel modello in cui viene utilizzato "has_attached_file" e specificare i tipi di file che si desidera consentire.

Ecco un esempio da un'applicazione in cui gli utenti caricano un avatar per il loro profilo:

has_attached_file :avatar, 
        :styles => { :thumb => "48x48#" }, 
        :default_url => "/images/avatars/missing_avatar.png", 
        :default_style => :thumb 

validates_attachment_content_type :avatar, :content_type => ["image/jpeg", "image/pjpeg", "image/png", "image/x-png", "image/gif"] 

La documentazione è qui http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html

+0

Grazie Beerlington! – sjsc

10

Un approccio è quello di utilizzare la convenzione "numero magico" per leggere il primo bit di un file.
http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html

Esempi:

 
    "BM" is a Bitmap image 
    "GIF8" is a GIF image 
    "\xff\xd8\xff\xe0" is a JPEG image 

esempio in Ruby:

 
    def bitmap?(data) 
    return data[0,2]=="MB" 
    end 

    def gif?(data) 
    return data[0,4]=="GIF8" 
    end 

    def jpeg?(data) 
    return data[0,4]=="\xff\xd8\xff\xe0" 
    end 

    def file_is_image?(filename) 
    f = File.open(filename,'rb') # rb means to read using binary 
    data = f.read(9)    # magic numbers are up to 9 bytes 
    f.close 
    return bitmap?(data) or gif?(data) or jpeg?(data) 
    end 

Perché usare questo anziché l'estensione del nome del file o il modulo filemagic?

Per rilevare il tipo di dati prima di scrivere qualsiasi dato sul disco. Ad esempio, possiamo leggere il flusso di dati di caricamento prima di scrivere qualsiasi dato sul disco. Se il numero magico non corrisponde al tipo di contenuto del modulo web, possiamo immediatamente segnalare un errore.

Implementiamo il nostro codice del mondo reale in modo leggermente diverso. Creiamo un hash: ogni chiave è una stringa di numeri magici, ogni valore è un simbolo come: bitmap,: gif,: jpeg, ecc. Se qualcuno vorrebbe vedere il nostro codice del mondo reale, sentiti libero di contattarmi qui.

+2

Un altro approccio al controllo di 'jpeg?' Sarebbe 'return data [0,3].bytes == [255, 216, 255] ' – n1313

7

Si prega di verificare una volta

MIME::Types.type_for('tmp/img1.jpg').first.try(:media_type) 
=> "image" 

MIME::Types.type_for('tmp/img1.jpeg').first.try(:media_type) 
=> "image" 

MIME::Types.type_for('tmp/img1.gif').first.try(:media_type) 
=> "image" 

MIME::Types.type_for('tmp/ima1.png').first.try(:media_type) 
=> "image" 
+0

Non so perché hai downvoted, ma funziona perfettamente con Rails 5.0! Grazie. – Vlad

0

In aggiunta alla risposta di Joel, in Rails 5 ho dovuto trasformare la stringa di confronto per un bytecode. Ad esempio:

def jpeg?(data) 
    return data[0,4]=="\xff\xd8\xff\xe0".b 
end