Проверка удаленного изображения на самом деле является файлом изображения в ruby?

Я пытаюсь выяснить, как я могу проверить, что то, что я подаю в несущую, на самом деле является изображением. Источник, из которого я получаю URL-адреса изображений, не возвращает мне все живые URL-адреса. Некоторых изображений уже нет. К сожалению, на самом деле он не возвращает правильные коды состояния или что-то еще, потому что я использовал некоторый код, чтобы проверить, существует ли удаленный файл, и он прошел эту проверку. Итак, теперь, чтобы быть в безопасности, я хотел бы проверить, что я возвращаю действительный файл изображения, прежде чем я продолжу и загружу его.

Вот код удаленной проверки файлов, который я использовал только для справки, но я бы предпочел что-то, что действительно может определить, что файлы являются изображениями.

require 'open-uri'
require 'net/http'

def remote_file_exists?(url)
    url = URI.parse(url)
    Net::HTTP.start(url.host, url.port) do |http|
      return http.head(url.request_uri).code == "200"
    end
end

person hadees    schedule 03.03.2012    source источник


Ответы (3)


Я бы проверил, возвращает ли служба правильные типы mime в HTTP-заголовке Content-Type. (вот список типов пантомимы)

Например, Content-Type домашней страницы StackOverflow — text/html; charset=utf-8, а Content-Type вашего изображения gravatar — image/png.

Чтобы проверить заголовок Content-Type для image в ruby ​​с помощью Net::HTTP, вы должны использовать следующее:

def remote_file_exists?(url)
    url = URI.parse(url)
    Net::HTTP.start(url.host, url.port) do |http|
      return http.head(url.request_uri)['Content-Type'].start_with? 'image'
    end
end
person Rick Button    schedule 03.03.2012
comment
В итоге я сначала проверил код состояния, чтобы убедиться, что это 200, а затем использовал ваш код. Что-то вроде return (head.code == "200") ? head['Content-Type'].start_with?('image') : false - person hadees; 06.03.2012
comment
Это должно сработать. Вы также должны спросить поставщика услуг, почему он возвращает код состояния 200, когда ресурс фактически не существует. - person Rick Button; 06.03.2012
comment
Да, это хороший вопрос, но я предполагаю, что они недостаточно техничны, чтобы ответить на него. Также у меня нет прямого доступа к ним. Надеюсь, это сработает в большинстве случаев. - person hadees; 06.03.2012
comment
Во многих случаях заголовки можно довольно легко подделать, поэтому полагаться исключительно на MIME-тип кажется несколько опасным и, возможно, небезопасным. Возможно, имеет смысл использовать ruby-filemagic для проверки типа по магическому номеру вместо этого или, по крайней мере, дополнительно. - person jaydel; 29.07.2012
comment
Судя по его последнему комментарию (ответ на мой комментарий), он, кажется, использует один источник для своих изображений. Если бы он сканировал много сайтов, я бы ему не доверял, но если это один доверенный источник, то он должен быть в порядке. - person Rick Button; 30.07.2012
comment
Это решение работает, но более короткая версия — stackoverflow.com/a/6400803/365950. - person Zubin; 14.08.2012

Ответ Рика Баттона сработал для меня, но мне нужно было добавить поддержку SSL:

def self.remote_image_exists?(url)
  url = URI.parse(url)
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = (url.scheme == "https")

  http.start do |http|
    return http.head(url.request_uri)['Content-Type'].start_with? 'image'
  end
end
person machineboy2045    schedule 14.01.2015

В итоге я использовал HTTParty для этого. Время ожидания ответа на запрос .net от Рика Баттона истекло.

  def remote_file_exists?(url)
    response = HTTParty.get(url)
    response.code == 200 && response.headers['Content-Type'].start_with? 'image'
  end

https://github.com/jnunemaker/httparty

person Hans Hauge    schedule 24.07.2014