List of usage examples for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED
int SC_NOT_MODIFIED
To view the source code for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED.
Click Source Link
From source file:org.ocpsoft.rewrite.servlet.config.proxy.ProxyServlet.java
protected boolean doResponseRedirectOrNotModifiedLogic(HttpServletRequest servletRequest, HttpServletResponse servletResponse, HttpResponse proxyResponse, int statusCode) throws ServletException, IOException { /*// ww w.ja v a2 s.co m * Check if the proxy response is a redirect. The following code is adapted from * org.tigris.noodle.filters.CheckForRedirect */ if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */ && statusCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) { Header locationHeader = proxyResponse.getLastHeader(HttpHeaders.LOCATION); if (locationHeader == null) { throw new ServletException("Received status code: " + statusCode + " but no " + HttpHeaders.LOCATION + " header was found in the response"); } /* * Modify the redirect to go to this proxy servlet rather that the proxied host */ String locStr = rewriteUrlFromResponse(servletRequest, locationHeader.getValue()); servletResponse.sendRedirect(locStr); return true; } /* * 304 needs special handling. See: http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304 . We get a 304 * whenever passed an 'If-Modified-Since' header and the data on disk has not changed; server responds w/ a 304 * saying I'm not going to send the body because the file has not changed. */ if (statusCode == HttpServletResponse.SC_NOT_MODIFIED) { servletResponse.setIntHeader(HttpHeaders.CONTENT_LENGTH, 0); servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return true; } return false; }
From source file:freeciv.servlet.ProxyServlet.java
/** * Executes the {@link HttpMethod} passed in and sends the proxy response * back to the client via the given {@link HttpServletResponse} * @param httpMethodProxyRequest An object representing the proxy request to be made * @param httpServletResponse An object by which we can send the proxied * response back to the client * @throws IOException Can be thrown by the {@link HttpClient}.executeMethod * @throws ServletException Can be thrown to indicate that another error has occurred */// w w w.j av a 2 s.c o m private void executeProxyRequest(HttpMethod httpMethodProxyRequest, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { httpMethodProxyRequest.setFollowRedirects(false); String port = "" + httpServletRequest.getSession().getAttribute("civserverport"); String host = "" + httpServletRequest.getSession().getAttribute("civserverhost"); String username = "" + httpServletRequest.getSession().getAttribute("username"); httpMethodProxyRequest.addRequestHeader("civserverport", port); httpMethodProxyRequest.addRequestHeader("civserverhost", host); httpMethodProxyRequest.addRequestHeader("username", username); int intProxyResponseCode = 0; // Execute the request try { intProxyResponseCode = client.executeMethod(httpMethodProxyRequest); } catch (IOException ioErr) { //- If an I/O (transport) error occurs. Some transport exceptions can be recovered from. //- If a protocol exception occurs. Usually protocol exceptions cannot be recovered from. OutputStream outputStreamClientResponse = httpServletResponse.getOutputStream(); httpServletResponse.setStatus(502); outputStreamClientResponse .write("Freeciv web client proxy not responding (most likely died).".getBytes()); httpMethodProxyRequest.releaseConnection(); return; } // Check if the proxy response is a redirect // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect // Hooray for open source software if (intProxyResponseCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */ && intProxyResponseCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) { String stringStatusCode = Integer.toString(intProxyResponseCode); String stringLocation = httpMethodProxyRequest.getResponseHeader(STRING_LOCATION_HEADER).getValue(); if (stringLocation == null) { httpMethodProxyRequest.releaseConnection(); throw new ServletException("Recieved status code: " + stringStatusCode + " but no " + STRING_LOCATION_HEADER + " header was found in the response"); } // Modify the redirect to go to this proxy servlet rather that the proxied host String stringMyHostName = httpServletRequest.getServerName(); if (httpServletRequest.getServerPort() != 80) { stringMyHostName += ":" + httpServletRequest.getServerPort(); } stringMyHostName += httpServletRequest.getContextPath(); httpServletResponse.sendRedirect( stringLocation.replace(getProxyHostAndPort() + this.getProxyPath(), stringMyHostName)); httpMethodProxyRequest.releaseConnection(); return; } else if (intProxyResponseCode == HttpServletResponse.SC_NOT_MODIFIED) { // 304 needs special handling. See: // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304 // We get a 304 whenever passed an 'If-Modified-Since' // header and the data on disk has not changed; server // responds w/ a 304 saying I'm not going to send the // body because the file has not changed. httpServletResponse.setIntHeader(STRING_CONTENT_LENGTH_HEADER_NAME, 0); httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED); httpMethodProxyRequest.releaseConnection(); return; } // Pass the response code back to the client httpServletResponse.setStatus(intProxyResponseCode); // Pass response headers back to the client Header[] headerArrayResponse = httpMethodProxyRequest.getResponseHeaders(); for (Header header : headerArrayResponse) { httpServletResponse.setHeader(header.getName(), header.getValue()); } // Send the content to the client InputStream inputStreamProxyResponse = httpMethodProxyRequest.getResponseBodyAsStream(); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStreamProxyResponse); OutputStream outputStreamClientResponse = httpServletResponse.getOutputStream(); int intNextByte; while ((intNextByte = bufferedInputStream.read()) != -1) { outputStreamClientResponse.write(intNextByte); } httpMethodProxyRequest.releaseConnection(); }
From source file:org.dspace.app.rest.utils.MultipartFileSenderTest.java
/** * If ETAG is equal to that of the requested Resource then this should return 304 * * @throws Exception/*from w w w. j a v a2 s. c om*/ */ @Test public void testIfNoneMatchFail() throws Exception { MultipartFileSender multipartFileSender = MultipartFileSender.fromInputStream(is).with(requestWrapper) .with(responseWrapper).withFileName(fileName).withChecksum(checksum).withMimetype(mimeType) .withLength(length); when(request.getHeader(eq("If-None-Match"))).thenReturn(checksum); multipartFileSender.isValid(); assertEquals(HttpServletResponse.SC_NOT_MODIFIED, responseWrapper.getStatusCode()); }
From source file:httpUtils.HttpUtils.java
/** * Parse the request headers, build the response, stream back file * @param request/* ww w . j av a 2 s . co m*/ * @param response * @param dataStream * @param fileLength * @param fileName * @param fileLastModified * @param contentType * @return */ private static HttpServletResponse getFileAsStream(HttpServletRequest request, HttpServletResponse response, InputStream dataStream, long fileLength, String fileName, long fileLastModified, String contentType) { if (dataStream == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); return response; } if (StringUtils.isEmpty(fileName) || fileLastModified == 0L) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return response; } String ifNoneMatch = request.getHeader("If-None-Match"); if (ifNoneMatch != null && matches(ifNoneMatch, fileName)) { response.setHeader("ETag", fileName); response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return response; } long ifModifiedSince = request.getDateHeader("If-Modified-Since"); if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > fileLastModified) { response.setHeader("ETag", fileName); response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return response; } String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !matches(ifMatch, fileName)) { response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); return response; } long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since"); if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= fileLastModified) { response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); return response; } Range full = new Range(0, fileLength - 1, fileLength); List<Range> ranges = new ArrayList<Range>(); String range = request.getHeader("Range"); if (range != null) { if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { response.setHeader("Content-Range", "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return response; } String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(fileName)) { try { long ifRangeTime = request.getDateHeader("If-Range"); if (ifRangeTime != -1) { ranges.add(full); } } catch (IllegalArgumentException ignore) { ranges.add(full); } } if (ranges.isEmpty()) { for (String part : range.substring(6).split(",")) { // Assuming a file with length of 100, the following // examples returns bytes at: // 50-80 (50 to 80), 40- (40 to length=100), -20 // (length-20=80 to length=100). long start = sublong(part, 0, part.indexOf("-")); long end = sublong(part, part.indexOf("-") + 1, part.length()); if (start == -1) { start = fileLength - end; end = fileLength - 1; } else if (end == -1 || end > fileLength - 1) { end = fileLength - 1; } // Check if Range is syntactically valid. If not, then // return 416. if (start > end) { response.setHeader("Content-Range", "bytes */" + fileLength); // Required // in // 416. response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return response; } // Add range. ranges.add(new Range(start, end, fileLength)); } } } // Get content type by file name and set content disposition. String disposition = "inline"; // If content type is unknown, then set the default value. // For all content types, see: // http://www.w3schools.com/media/media_mimeref.asp // To add new content types, add new mime-mapping entry in web.xml. if (contentType == null) { contentType = "application/octet-stream"; } else if (!contentType.startsWith("image")) { // Else, expect for images, determine content disposition. If // content type is supported by // the browser, then set to inline, else attachment which will pop a // 'save as' dialogue. String accept = request.getHeader("Accept"); disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment"; } // Initialize response. response.reset(); response.setBufferSize(HttpUtils.DEFAULT_BUFFER_SIZE); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", fileName); response.setDateHeader("Last-Modified", fileLastModified); response.setDateHeader("Expires", System.currentTimeMillis() + HttpUtils.DEFAULT_EXPIRE_TIME); // Send requested file (part(s)) to client // ------------------------------------------------ // Prepare streams. InputStream input = null; OutputStream output = null; try { // Open streams. input = new BufferedInputStream(dataStream); output = response.getOutputStream(); if (ranges.isEmpty() || ranges.get(0) == full) { // Return full file. Range r = full; response.setContentType(contentType); response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total); response.setHeader("Content-Length", String.valueOf(r.length)); copy(input, output, fileLength, r.start, r.length); } else if (ranges.size() == 1) { // Return single part of file. Range r = ranges.get(0); response.setContentType(contentType); response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total); response.setHeader("Content-Length", String.valueOf(r.length)); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206. // Copy single part range. copy(input, output, fileLength, r.start, r.length); } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + HttpUtils.MULTIPART_BOUNDARY); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206. // Cast back to ServletOutputStream to get the easy println // methods. ServletOutputStream sos = (ServletOutputStream) output; // Copy multi part range. for (Range r : ranges) { // Add multipart boundary and header fields for every range. sos.println(); sos.println("--" + HttpUtils.MULTIPART_BOUNDARY); sos.println("Content-Type: " + contentType); sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total); // Copy single part range of multi part range. copy(input, output, fileLength, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + HttpUtils.MULTIPART_BOUNDARY + "--"); } } catch (Exception e) { log.error("get file as stream failed", e); } finally { // Gently close streams. close(output); close(input); close(dataStream); } return response; }
From source file:org.alfresco.repo.web.scripts.content.ContentStreamer.java
/** * Streams the content on a given node's content property to the response of the web script. * * @param req Request/*from ww w . j a v a2 s .c o m*/ * @param res Response * @param nodeRef The node reference * @param propertyQName The content property name * @param attach Indicates whether the content should be streamed as an attachment or not * @param attachFileName Optional file name to use when attach is <code>true</code> * @throws IOException */ public void streamContent(WebScriptRequest req, WebScriptResponse res, NodeRef nodeRef, QName propertyQName, boolean attach, String attachFileName, Map<String, Object> model) throws IOException { if (logger.isDebugEnabled()) logger.debug("Retrieving content from node ref " + nodeRef.toString() + " (property: " + propertyQName.toString() + ") (attach: " + attach + ")"); // TODO // This was commented out to accomadate records management permissions. We need to review how we cope with this // hard coded permission checked. // check that the user has at least READ_CONTENT access - else redirect to the login page // if (permissionService.hasPermission(nodeRef, PermissionService.READ_CONTENT) == AccessStatus.DENIED) // { // throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Permission denied"); // } // check If-Modified-Since header and set Last-Modified header as appropriate Date modified = (Date) nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED); if (modified != null) { long modifiedSince = -1; String modifiedSinceStr = req.getHeader("If-Modified-Since"); if (modifiedSinceStr != null) { try { modifiedSince = dateFormat.parse(modifiedSinceStr).getTime(); } catch (Throwable e) { if (logger.isInfoEnabled()) logger.info("Browser sent badly-formatted If-Modified-Since header: " + modifiedSinceStr); } if (modifiedSince > 0L) { // round the date to the ignore millisecond value which is not supplied by header long modDate = (modified.getTime() / 1000L) * 1000L; if (modDate <= modifiedSince) { res.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } } } } // get the content reader ContentReader reader = contentService.getReader(nodeRef, propertyQName); if (reader == null || !reader.exists()) { throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to locate content for node ref " + nodeRef + " (property: " + propertyQName.toString() + ")"); } // Stream the content streamContentImpl(req, res, reader, nodeRef, propertyQName, attach, modified, modified == null ? null : Long.toString(modified.getTime()), attachFileName, model); }
From source file:com.bstek.dorado.web.resolver.AbstractWebFileResolver.java
protected void outputResourcesWrapper(ResourcesWrapper resourcesWrapper, HttpServletRequest request, HttpServletResponse response) throws Exception { if (resourcesWrapper.getHttpStatus() != 0) { response.setStatus(resourcesWrapper.getHttpStatus()); } else {/* ww w. j a va2s . c o m*/ // ?Client??-1 long cachedLastModified = request.getDateHeader(HttpConstants.IF_MODIFIED_SINCE); // ?Server?? long lastModified = resourcesWrapper.getLastModified(); // ?Client if (lastModified != 0 && cachedLastModified != 0 && Math.abs(lastModified - cachedLastModified) < ONE_SECOND) { // ?Server???Client response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } else { String contentType = getContentType(resourcesWrapper); response.setContentType(contentType); // Client?? SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); dateFormat.setTimeZone(GMT_TIME_ZONE); response.addHeader(HttpConstants.LAST_MODIFIED, dateFormat.format(new Date(lastModified))); Resource[] resources = resourcesWrapper.getResources(); OutputStream out = getOutputStream(request, response, resourcesWrapper); try { for (int i = 0; i < resources.length; i++) { if (i > 0 && contentType.contains("text")) { out.write("\n".getBytes(response.getCharacterEncoding())); } outputFile(out, resources[i]); } } finally { try { out.close(); } catch (IOException e) { // do nothing } } } } }
From source file:com.ecyrd.jspwiki.attachment.AttachmentServlet.java
/** * Serves a GET with two parameters: 'wikiname' specifying the wikiname * of the attachment, 'version' specifying the version indicator. * /*from w w w . j a v a 2s. c o m*/ * {@inheritDoc} */ // FIXME: Messages would need to be localized somehow. public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { WikiContext context = m_engine.createContext(req, WikiContext.ATTACH); String version = req.getParameter(HDR_VERSION); String nextPage = req.getParameter("nextpage"); String msg = "An error occurred. Ouch."; int ver = WikiProvider.LATEST_VERSION; AttachmentManager mgr = m_engine.getAttachmentManager(); AuthorizationManager authmgr = m_engine.getAuthorizationManager(); String page = context.getPage().getName(); if (page == null) { log.info("Invalid attachment name."); res.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } OutputStream out = null; InputStream in = null; try { log.debug("Attempting to download att " + page + ", version " + version); if (version != null) { ver = Integer.parseInt(version); } Attachment att = mgr.getAttachmentInfo(page, ver); if (att != null) { // // Check if the user has permission for this attachment // Permission permission = PermissionFactory.getPagePermission(att, "view"); if (!authmgr.checkPermission(context.getWikiSession(), permission)) { log.debug("User does not have permission for this"); res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } // // Check if the client already has a version of this attachment. // if (HttpUtil.checkFor304(req, att)) { log.debug("Client has latest version already, sending 304..."); res.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } String mimetype = getMimeType(context, att.getFileName()); res.setContentType(mimetype); // // We use 'inline' instead of 'attachment' so that user agents // can try to automatically open the file. // res.addHeader("Content-Disposition", "inline; filename=\"" + att.getFileName() + "\";"); res.addDateHeader("Last-Modified", att.getLastModified().getTime()); if (!att.isCacheable()) { res.addHeader("Pragma", "no-cache"); res.addHeader("Cache-control", "no-cache"); } // If a size is provided by the provider, report it. if (att.getSize() >= 0) { // log.info("size:"+att.getSize()); res.setContentLength((int) att.getSize()); } out = res.getOutputStream(); in = mgr.getAttachmentStream(context, att); int read = 0; byte[] buffer = new byte[BUFFER_SIZE]; while ((read = in.read(buffer)) > -1) { out.write(buffer, 0, read); } if (log.isDebugEnabled()) { msg = "Attachment " + att.getFileName() + " sent to " + req.getRemoteUser() + " on " + req.getRemoteAddr(); log.debug(msg); } if (nextPage != null) res.sendRedirect(nextPage); return; } msg = "Attachment '" + page + "', version " + ver + " does not exist."; log.info(msg); res.sendError(HttpServletResponse.SC_NOT_FOUND, msg); return; } catch (ProviderException pe) { msg = "Provider error: " + pe.getMessage(); log.debug("Provider failed while reading", pe); // // This might fail, if the response is already committed. So in that // case we just log it. // try { res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg); } catch (IllegalStateException e) { } return; } catch (NumberFormatException nfe) { msg = "Invalid version number (" + version + ")"; res.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); return; } catch (SocketException se) { // // These are very common in download situations due to aggressive // clients. No need to try and send an error. // log.debug("I/O exception during download", se); return; } catch (IOException ioe) { // // Client dropped the connection or something else happened. // We don't know where the error came from, so we'll at least // try to send an error and catch it quietly if it doesn't quite work. // msg = "Error: " + ioe.getMessage(); log.debug("I/O exception during download", ioe); try { res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg); } catch (IllegalStateException e) { } return; } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } // // Quite often, aggressive clients close the connection when they have // received the last bits. Therefore, we close the output, but ignore // any exception that might come out of it. // if (out != null) { try { out.close(); } catch (IOException e) { } } } }
From source file:ch.entwine.weblounge.test.harness.content.CacheTest.java
/** * Tests if the modification date matches that of the most recent element on a * page rather than the page's modification date. * /*from w w w . j ava 2s . c o m*/ * @param serverUrl * the server url * @throws Exception * if the test fails */ private void testInheritedModifcation(String serverUrl) throws Exception { logger.info("Preparing test of cache headers influenced by inherited updated content"); DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); df.setTimeZone(TimeZone.getTimeZone("GMT")); // Prepare the request logger.info("Gathering original modification date"); String requestUrl = UrlUtils.concat(serverUrl, hostPage, language.getIdentifier()); logger.info("Sending request to {}", requestUrl); HttpGet request = new HttpGet(requestUrl); request.addHeader("X-Cache-Debug", "yes"); String[][] params = new String[][] { {} }; // Send and the request and examine the response. Keep the modification // date. HttpClient httpClient = new DefaultHttpClient(); try { HttpResponse response = TestUtils.request(httpClient, request, params); int statusCode = response.getStatusLine().getStatusCode(); boolean okOrNotModified = statusCode == HttpServletResponse.SC_OK || statusCode == HttpServletResponse.SC_NOT_MODIFIED; assertTrue(okOrNotModified); // Get the ETag header assertNotNull(response.getHeaders("ETag")); assertEquals(1, response.getHeaders("ETag").length); String hostOrignalETag = response.getHeaders("ETag")[0].getValue(); // Get the Modified header assertNotNull(response.getHeaders("Last-Modified")); assertEquals(1, response.getHeaders("Last-Modified").length); Date hostModified = df.parse(response.getHeaders("Last-Modified")[0].getValue()); response.getEntity().consumeContent(); httpClient.getConnectionManager().shutdown(); logger.info("Updating linked page"); update(serverUrl, linkedPageId); // Give the cache time to persist the entry Thread.sleep(1000); httpClient = new DefaultHttpClient(); // Test using ETag and modified header request.setHeader("If-None-Match", hostOrignalETag); request.setHeader("If-Modified-Since", df.format(hostModified)); response = TestUtils.request(httpClient, request, params); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); // Get the Expires header assertNotNull(response.getHeaders("Expires")); assertEquals(1, response.getHeaders("Expires").length); // We are explicitly not checking for equality with the previously // received value, since on first request, that value is not yet correct // Get the ETag header and make sure it has been updated assertNotNull(response.getHeaders("ETag")); assertEquals(1, response.getHeaders("ETag").length); assertFalse(hostOrignalETag.equals(response.getHeaders("ETag")[0].getValue())); // Test the modified header and make sure it has been updated assertNotNull(response.getHeaders("Last-Modified")); assertEquals(1, response.getHeaders("Last-Modified").length); Date newModified = df.parse(response.getHeaders("Last-Modified")[0].getValue()); assertTrue(hostModified.before(newModified)); } finally { httpClient.getConnectionManager().shutdown(); } }
From source file:siddur.solidtrust.image.ImageController.java
@RequestMapping(value = "/images/{filename:.+}") public void serveImage(HttpServletRequest req, HttpServletResponse resp, @PathVariable("filename") String filename, @RequestParam(value = "s", required = false) String scope) throws IOException { String filepath = filename;/*w w w . j a va2 s.c o m*/ if (scope != null) { filepath = scope + "/" + filepath; } //404 File f = new File(FileSystemUtil.getImageDir(), filepath); if (!f.exists()) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); return; } //304 long lastModifiedTimestamp = f.lastModified(); long ifModifiedSince = req.getDateHeader("If-Modified-Since"); boolean notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000)); if (notModified) { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } else { resp.setDateHeader("Last-Modified", lastModifiedTimestamp); } //length resp.setContentLength((int) f.length()); //content type resp.setContentType("image/jpg"); //response FileCopyUtils.copy(new FileInputStream(f), resp.getOutputStream()); }