2010-02-08 13 views
15

Jak sprawdzić, czy plik jest obrazem? Myślę, że możesz użyć metody takiej jak:Ruby on Rails: Jak sprawdzić, czy plik jest obrazem?

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

Ale to może być trochę nieefektywne i niepoprawne. Jakieś pomysły?

(używam plugin spinacza, btw, ale nie widzę żadnych metod, aby określić, czy plik jest obrazem w spinacz)

Odpowiedz

12

chciałbym użyć ruby-filemagic klejnot, który jest wiążący dla Ruby libmagic.

+0

Dziękuję Sinan za świetny link! Nie wiedziałem, że to istnieje. Dziękuję Ci. – sjsc

+0

Polecenie pliku jest naprawdę dobre, więc to opakowanie powinno wykonać zadanie. – tadman

1

imagemagick ma polecenie o nazwie tożsamość, które obsługuje to - sprawdź w dokumentacji spinacza - prawdopodobnie istnieje sposób, aby poradzić sobie z tym z poziomu aplikacji RoR.

+0

Dzięki za napiwek Claude i John o tożsamości. Będę miał czek. Dziękuję bardzo za polecenie. – sjsc

7

Ponieważ używasz spinacza, możesz użyć wbudowanej metody "validates_attachment_content_type" w modelu, w którym jest używany "has_attached_file", i określić typy plików, które chcesz dopuścić.

Oto przykład z aplikacji, gdzie użytkownicy wgrać awatar do swojego profilu:

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"] 

dokumentacja jest tutaj http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html

+0

Dziękuję Beerlington! – sjsc

10

Jednym ze sposobów jest użycie „magiczna liczba” Konwencja czytać pierwszy bity pliku.
http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html

Przykłady:

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

przykład w 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 

Dlaczego to wykorzystać zamiast rozszerzenia nazwy pliku lub modułu filemagic?

Aby wykryć typ danych przed zapisaniem danych na dysku. Na przykład możemy odczytać przesyłanie strumienia danych przed zapisaniem jakichkolwiek danych na dysk. Jeśli magiczna liczba nie pasuje do typu zawartości formularza internetowego, możemy natychmiast zgłosić błąd.

Implementujemy nasz kod realnego świata nieco inaczej. Tworzymy hash: każdy klucz jest magicznym ciągiem znaków, każda wartość jest symbolem takim jak: bitmap,: gif,: jpeg, itp. Jeśli ktoś chciałby zobaczyć nasz kod w świecie rzeczywistym, skontaktuj się ze mną tutaj.

+2

Innym podejściem przy sprawdzaniu "jpeg?" Byłoby "zwracanie danych [0,3].Bajty == [255, 216, 255] ' – n1313

7

Proszę sprawdzić to raz

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

Nie wiem, dlaczego zostałeś cenzurowany, ale działa to doskonale w Railsach 5.0! Dziękuję Ci. – Vlad

0

Jako dodatek do odpowiedzi Joela, w Rails 5 musiałam przekształcić ciąg porównaniu do kodu bajtowego. Np .:

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