caching images served by servlet

2019-01-11 05:23发布

问题:

I'm serving up images from my servlet. The response content type is image/jpeg. I find that images requested from my servlet are not cached. How do I get them to be cached like file image requests normally are? I tried setting Cache-Control: public but to no avail.

回答1:

The default servlet serving static content in containers like Tomcat doesn't set any cache control headers. You don't need write a servlet just for that. Just create a filter like this,

public void doFilter(ServletRequest request,
        ServletResponse response,
        FilterChain chain) 
    throws IOException, ServletException {

    long expiry = new Date().getTime() + cacheAge*1000;

    HttpServletResponse httpResponse = (HttpServletResponse)response;
    httpResponse.setDateHeader("Expires", expiry);
    httpResponse.setHeader("Cache-Control", "max-age="+ cacheAge);

    chain.doFilter(request, response);

 }

Whenever you want add cache control, just add the filter to the resources in web.xml. For example,

<filter>
    <filter-name>CacheControl</filter-name>
    <filter-class>filters.CacheControlFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>CacheControl</filter-name>
    <url-pattern>/images/*</url-pattern>
</filter-mapping>


回答2:

You need to send the ETag, Last-Modified and Expires headers along the response. The ETag represents the unique identifier of the file (usually composed based on a combination of filename, filesize and lastmodified timestamp). The Last-Modified represents the last modified timestamp of the file. The Expires header denotes how long the client is allowed to keep the file in cache. If the cache has been expired and the ETag or Last-Modified are available, then the client will send a HEAD request to check if the file needs to be renewed. If not, then the Expires will just be postponed again accordingly.

You can find here a servlet example which handles this all (and download resumes and automatic GZIP): FileServlet supporting resume and GZIP



回答3:

For example, if you want to cache them for 1 month:

Calendar inOneMonth = Calendar.getInstance();
inOneMonth.add(Calendar.MONTH, 1);

response.setDateHeader("Expires", inOneMonth.getTimeInMillis());

(this is in a Filter that handles the *.jpg pattern, for example)

But images should be cached by default - check your filters and configurations to see if something isn't setting the cache parameters incorrectly.



回答4:

Ok.. looks like the default header fields should enable caching. I found a solution in another forum. Apparently, you need to explicitly set a content-length in the response. Wonder why though. I thought the HttpServletResponse would do that for us. Anyway, it worked like a charm and the image is getting cached nicely.