Подтвердить что ты не робот

Отображение изображения

Так что это должно быть довольно легко, но я не могу заставить его работать.

У меня есть метод контроллера, который находит изображение на основе запроса, затем вывод кэшируется. Изображение может быть удаленным (flickr, google images и т.д.), Или оно может быть локальным. Независимо от источника, мне просто нужно взять содержимое файла изображения и передать его пользователю. По существу, прокси. Прохождение через удаленные изображения, кажется, работает нормально, но прохождение через локальные изображения дает мне:

invalid byte sequence in UTF-8

Итак, вот что я получил. Я надеюсь, что кто-то сможет решить проблему или вести меня в лучшем направлении с моим кодом.

def image_proxy
  query = params[:query]
  image_url = get_image_url(query) # returns an absolute local file path or a URL

  response.headers['Cache-Control'] = "public, max-age=#{12.hours.to_i}"
  response.headers['Content-Type'] = 'image/jpeg'
  response.headers['Content-Disposition'] = 'inline'
  render :text => open(image_url).read
end

Удаленные файлы работают нормально, локальные файлы не работают.

Бонус для всех, кто может помочь решить эту проблему:

  • Мне нужно установить правильный тип контента. Удаленные URL-адреса изображений не говорят мне тип изображения, я просто получаю URL-адрес, и иногда URL-адрес не содержит расширение. Поэтому я выбрал jpeg, потому что он работает независимо от типа изображения, отправленного мне.

Спасибо!

4b9b3361

Ответ 1

Попробуйте использовать render :text => open(image_url, "rb").read, который сообщает Ruby, что файл, который он открывает, является двоичным и не пытается прочитать его как текст.

изменить

В качестве бонусного вопроса вы можете прочитать первые несколько байтов и посмотреть, что они содержат. PNG всегда начинается с значений шестнадцатеричного байта 89 50 4E 47 0D 0A 1A 0A (или десятичных значений 137 80 78 71 13 10 26 10).

В Википедии есть список магических номеров, используемых для идентификации файла, на которые вы можете посмотреть. Просто создайте метод, который читает первые несколько байтов и сравнивает его с этим.

Ответ 2

Какая версия Rails? Для Rails 3 вы должны посмотреть на методы потоковой передачи, которые были добавлены. send_data будет правильным способом отправки двоичных данных. Если изображения являются локальными, и ваш веб-сервер поддерживает его, вы можете использовать send_file, который не будет блокировать экземпляр rails, пока пользователь загружает изображение.