Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly return an image in the response in Spring app?

I 'm using Spring 3.0.1.RELEASE for my webapp (and i have no way for upgrading it) and i'm trying to render some images from database on web-page.

I have following simple Spring configs:

spring-application.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <task:annotation-driven />

    <context:annotation-config />

    <context:spring-configured />

    <context:component-scan base-package="com.me" />

    <bean id="hibernateSessionFactory" class="com.me.dbaccess.HibernateSessionFactory">
        <constructor-arg ref="sessionFactory"/>
    </bean>
</beans>

spring-mvc.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <mvc:annotation-driven/>

    <bean id="tilesViewResolver" class="com.me.util.TilesExposingBeansViewResolver">
        <property name="viewClass" value="com.me.util.TilesExposingBeansView"/>
        <property name="exposeContextBeansAsAttributes" value="true"/>
    </bean>

    <bean id="tilesConfigurer"
          class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/config/tiles-defs.xml</value>
            </list>
        </property>
    </bean>
</beans>

I have following controller:

@Controller
public class PhotoController {
    @RequestMapping("/carPhoto.html")
    @ResponseBody
    public byte[] getCarPhoto(
            @RequestParam(UrlParameters.PHOTO_ID) Integer photoId,
            @RequestParam(UrlParameters.PHOTO_TYPE) String photoType) {
        //return image's bytes array from db by photo Id and Type;
    }
}

And finally, I have simple jsp-page:

<%@page contentType="text/html; charset=utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<img id="photoImage" src="<c:url value="/carPhoto.html?photoType=1&photoId=22556793"/>" />

If I open this page - I can see this image without any problems.

But if I copy image "src" attribute and paste it in browser's address bar (Firefox 19.0.2) - then browser offers me to save carPhoto.html, instead of just render the image. Should I perform some additional setup?

like image 368
kumade Avatar asked Mar 29 '13 13:03

kumade


2 Answers

There are several ways. Easiest is to use @ResponseBody with a byte[] as your return type, set your Content-Type and such, the write the bytes to the output stream using the HttpServletResponse.

A more elegant solution (IMO) would be to return a ModelAndView, then set the View on that to a custom view that sets the proper headers (Content-Type and such) and writes out the bytes to the HttpServletResponse's output stream.


like image 41
CodeChimp Avatar answered Nov 14 '22 20:11

CodeChimp


The problem is, that you have to specify the mime type (and if your image is larger you will need to specify its length too).

An other solution () is to return a Spring ResponseEntity or HttpEntity (HttpEntity is enough if you always return http status code 200, ResponseEntity (a subclass of HttpEntity) is for example needed if you want to return other http status codes, like not found).

@Controller
public class PhotoController {
    @RequestMapping("/carPhoto.html")
    @ResponseBody
    public HttpEntity<byte[]> getCarPhoto(
            @RequestParam(UrlParameters.PHOTO_ID) Integer photoId,
            @RequestParam(UrlParameters.PHOTO_TYPE) String photoType) {


        byte[] image = image's bytes array from db by photo Id and Type;

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG); //or what ever type it is
        headers.setContentLength(image.length);
        return new HttpEntity<byte[]>(image, headers);
    }
}
like image 129
Ralph Avatar answered Nov 14 '22 20:11

Ralph