Отображение изображения
Так что это должно быть довольно легко, но я не могу заставить его работать.
У меня есть метод контроллера, который находит изображение на основе запроса, затем вывод кэшируется. Изображение может быть удаленным (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, потому что он работает независимо от типа изображения, отправленного мне.
Спасибо!
Ответы
Ответ 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, пока пользователь загружает изображение.