2010-02-08 38 views
15

Làm cách nào để kiểm tra xem tệp có phải là hình ảnh không? Tôi nghĩ bạn có thể sử dụng một phương pháp như vậy:Ruby on Rails: Làm cách nào để kiểm tra xem tệp có phải là hình ảnh không?

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

Nhưng điều đó có thể hơi kém hiệu quả và không chính xác. Bất kỳ ý tưởng?

(Tôi đang sử dụng plugin kẹp giấy, btw, nhưng tôi không thấy bất kỳ phương pháp để xác định xem một tập tin là một hình ảnh trong kẹp giấy)

Trả lời

12

Tôi sẽ sử dụng viên ngọc ruby-filemagic đó là một Ruby bắt buộc đối với libmagic.

+0

Cảm ơn bạn Sinan vì liên kết tuyệt vời! Tôi không biết điều đó tồn tại. Cảm ơn bạn. – sjsc

+0

Lệnh tệp thực sự tuyệt vời cho việc này, vì vậy trình bao bọc này nên thực hiện công việc. – tadman

1

imagemagick có lệnh gọi là nhận dạng xử lý việc này - kiểm tra w/tài liệu kẹp giấy - có thể có cách để xử lý việc này từ trong ứng dụng RoR của bạn.

+0

Cảm ơn Claude và John về danh tính. Tôi sẽ kiểm tra. Cảm ơn bạn rất nhiều vì đã giới thiệu. – sjsc

7

Vì bạn đang sử dụng Paperclip, bạn có thể sử dụng phương thức "validates_attachment_content_type" trong mô hình mà "has_attached_file" được sử dụng và chỉ định loại tệp bạn muốn cho phép.

Dưới đây là một ví dụ từ một ứng dụng mà người dùng tải lên hình đại diện cho hồ sơ của họ:

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

Các tài liệu là ở đây http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html

+0

Cảm ơn bạn Beerlington! – sjsc

10

Một cách tiếp cận là sử dụng "con số kỳ diệu" ước để đọc đầu tiên bit của một tập tin.
http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html

Ví dụ:

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

Ví dụ trong 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 

Tại sao sử dụng này thay vì phần mở rộng tên tập tin hoặc các module filemagic?

Để phát hiện loại dữ liệu trước khi ghi bất kỳ dữ liệu nào vào đĩa. Ví dụ: chúng tôi có thể đọc luồng dữ liệu tải lên trước khi chúng tôi ghi bất kỳ dữ liệu nào vào đĩa. Nếu số ma thuật không khớp với loại nội dung biểu mẫu web, thì chúng tôi có thể báo cáo lỗi ngay lập tức.

Chúng tôi triển khai mã thực của chúng tôi hơi khác một chút. Chúng tôi tạo ra một băm: mỗi khóa là một chuỗi số ma thuật, mỗi giá trị là một biểu tượng như: bitmap,: gif,: jpeg, v.v. Nếu có ai muốn xem mã thế giới thực của chúng tôi, vui lòng liên hệ với tôi tại đây.

+2

Một cách tiếp cận khác khi kiểm tra 'jpeg? 'Sẽ là' dữ liệu trả về [0,3].bytes == [255, 216, 255] ' – n1313

7

Vui lòng kiểm tra nó một lần

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

Tôi không biết tại sao bạn bị downvoted nhưng điều này hoạt động hoàn toàn tốt trong Rails 5.0! Cảm ơn bạn. – Vlad

0

Như một sự bổ sung cho câu trả lời của Joel, trong Rails 5 Tôi phải chuyển đổi chuỗi so sánh với một bytecode. Ví dụ:

def jpeg?(data) 
    return data[0,4]=="\xff\xd8\xff\xe0".b 
end 
Các vấn đề liên quan