Кажется, я столкнулся с интересной проблемой, когда браузер успешно отображает изображение, сгенерированное моим веб-приложением Spring MVC, если URL-адрес моего контроллера установлен как SRC тега IMG , но отображает двоичные данные при переходе непосредственно к URL-адресу.
Мой Spring MVC Controller генерирует некоторый BufferedImage
(эскиз), преобразует его в байт []
и возвращает его непосредственно в тело ответа с помощью @ResponseBody
аннотация к методу контроллера. Я зарегистрировал org.springframework.http.converter.Конвертер сообщений ByteArrayHttpMessageConverter
с помощью AnnotationMethodHandlerAdapter
и даже установил для его свойства supportedMediaTypes
значение image / jpeg
, что на самом деле не помогло, поэтому я устанавливаю Заголовок Content-Type в ответе вручную в методе контроллера.
<img src="/images/thumbnail?id=1234" />
работает нормально и отображает изображение, однако переход непосредственно к SRC изображения (или щелчок правой кнопкой мыши и выбор «Просмотр изображения») приводит к отображению необработанных данных изображения.
Заголовки ответа, согласно Firebug, полученные от запроса на такой URL ( http: // localhost: 8888 / images / thumbnail? Id = F0snPkvwhtDbl8eutbuq ):
HTTP/1.1 200 OK
Expires: Wed, 21 Dec 2011 12:39:07 GMT
Cache-Control: max-age=2592000
Content-Type: image/jpeg
Content-Length: 6998
Server: Jetty(6.1.10)
Последнее слово: in Firebug, при нажатии на вкладку Response отображается изображение :-) Что я упускаю? Я думал, что браузер получает заголовки типа содержимого и длины содержимого, знает, что нужно ожидать изображения jpeg, получает необработанные данные для jpeg, а затем отображает jpeg на пустой вкладке браузера. Каким-то образом FF и Chrome отображают полученные необработанные данные изображения.
Код, который я использую:
@RequestMapping(value = "thumbnail", method = { RequestMethod.GET })
@ResponseBody
public byte[] getImageThumbnail(@RequestParam("id") String documentId, HttpServletResponse response) {
try {
Document document = documentService.getDocumentById(documentId);
InputStream imageInputStream = new FileInputStream(document.getUri());
response.setContentType("image/jpeg");
BufferedImage img = ImageIO.read(imageInputStream);
ResampleOp resampleOp = new ResampleOp(THUMBNAIL_DIMENSION);
BufferedImage thumbnail = resampleOp.filter(img, null);
return getDataFromBufferedImage(thumbnail);
} catch (Throwable t) {
return null; //return no data if document not found or whatever other issues are encountered
}
}
private byte[] getDataFromBufferedImage(BufferedImage thumbnail) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(thumbnail, "jpg", baos);
baos.flush();
return baos.toByteArray();
} finally {
baos.close();
}
}
=== UPDATE === Я последовал совету @BalusC и изменил URL-адрес, который создает миниатюру, чтобы она выглядела как настоящий файл .jpg. Это имело некоторую разницу в том, что теперь я могу «Сохранить изображение как», а имя файла больше не просто «эскиз», а «.jpg», что хорошо. Однако и Chrome, и FF (я даже не начал тестирование в IE) отображают необработанные данные JFIF при загрузке URL-адреса в новую вкладку / окно.Тем не менее, изображение отображается только в том случае, если URL-адрес находится в атрибуте SRC тега IMG и (благодаря кешированию браузера), когда пользователь выбирает Просмотр изображения на новой вкладке (но только если пользователь не обновляет вкладку, обновление вкладки будет повторно загружено JPEG и отобразить необработанные данные в окне).
РЕДАКТИРОВАТЬ Я только что протестировал это в IE9, и это единственный браузер, в котором он работает должным образом. Я могу напрямую перейти к URL-адресу и продолжать обновлять страницу, и я вижу, что мой контроллер поражен, а JPEG загружается в окно браузера. Превосходно. Теперь выясним, что не так с тем, как FF / CR обрабатывает отправляемый мной JPEG.
Дополнительная информация Я использую Spring версии 3.0.6.RELEASE Запуск веб-приложения с Jetty
РЕДАКТИРОВАТЬ
Я решил свою проблему by , а не , используя @ResponseBody
и BytArrayHttpMessageConverter
- Я попробовал обходной путь, предложенный в другом потоке здесь, на SO - просто записать байты непосредственно в ответ stream: IOUtils.copy (imageInputStream, response.getOutputStream ());
Это просто и работает, мне все еще любопытно, в чем заключалась странная проблема с тем, как браузеры загружали ответ в < img>
, но не непосредственно в окне браузера. Кто угодно может пролить свет на это, мне было бы очень интересно узнать больше. Я пока оставляю этот вопрос без ответа.