List of usage examples for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE
int SC_REQUESTED_RANGE_NOT_SATISFIABLE
To view the source code for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE.
Click Source Link
From source file:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_bad_symbols_in_range() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=bad"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals("", mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, mockHttpServletResponse.getStatus()); }
From source file:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_bad_range() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=5-1"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals("", mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, mockHttpServletResponse.getStatus()); }
From source file:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_out_of_range() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=50000-50100"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals("", mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, mockHttpServletResponse.getStatus()); }
From source file:netinf.node.cache.peerside.PeersideServlet.java
/** * HEAD and GET operations./*from w ww . java 2s. c om*/ * * @param req * The Request. * @param resp * The response. * @param writeContent * @throws IOException */ private void doHeadOrGet(HttpServletRequest req, HttpServletResponse resp, boolean writeContent) throws IOException { String elementKey = req.getPathInfo(); if (elementKey.startsWith("/") && elementKey.length() >= 1) { elementKey = elementKey.substring(1); } Element element = cache.get(elementKey); if (element == null) { resp.setStatus(HttpServletResponse.SC_NOT_FOUND); } else { byte[] content = (byte[]) element.getValue(); String range = req.getHeader("Range"); if (range != null) { if (range.matches("^bytes=(\\d+-\\d*|-\\d+)$")) { int contentLength = content.length; int offset = 0; int length = contentLength; range = range.split("=")[1]; if (range.startsWith("-")) { offset = contentLength - Integer.parseInt(range.substring(1)); } else if (range.endsWith("-")) { offset = Integer.parseInt(range.substring(0, range.length() - 1)); } else { String[] rangeParts = range.split("-"); offset = Integer.parseInt(rangeParts[0]); length = Integer.parseInt(rangeParts[1]) + 1; } if (offset <= length && offset <= contentLength) { length = length > contentLength ? contentLength : length; resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); resp.setContentLength(length - offset); resp.setHeader("Accept-Ranges", "bytes"); resp.setHeader("Content-Range", offset + "-" + (length - 1) + "/" + contentLength); if (writeContent) { IOUtils.copy(new ByteArrayInputStream(content, offset, length - offset), resp.getOutputStream()); } } else { resp.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); } } else { resp.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); } } else { resp.setStatus(HttpServletResponse.SC_OK); resp.setContentLength(content.length); resp.setHeader("Accept-Ranges", "bytes"); if (writeContent) { IOUtils.copy(new ByteArrayInputStream(content), resp.getOutputStream()); } } } }
From source file:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_out_of_range_in_multipart() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=0-5, 50000-50100"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals("", mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, mockHttpServletResponse.getStatus()); }
From source file:net.dorokhov.pony.web.server.common.StreamingViewRenderer.java
@Override protected void renderMergedOutputModel(Map objectMap, HttpServletRequest request, HttpServletResponse response) throws Exception { InputStream dataStream = (InputStream) objectMap.get(DownloadConstants.INPUT_STREAM); if (dataStream == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return;/* ww w.ja v a 2 s . c om*/ } long length = (Long) objectMap.get(DownloadConstants.CONTENT_LENGTH); String fileName = (String) objectMap.get(DownloadConstants.FILENAME); Date lastModifiedObj = (Date) objectMap.get(DownloadConstants.LAST_MODIFIED); if (StringUtils.isEmpty(fileName) || lastModifiedObj == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } long lastModified = lastModifiedObj.getTime(); String contentType = (String) objectMap.get(DownloadConstants.CONTENT_TYPE); // Validate request headers for caching --------------------------------------------------- // If-None-Match header should contain "*" or ETag. If so, then return 304. String ifNoneMatch = request.getHeader("If-None-Match"); if (ifNoneMatch != null && matches(ifNoneMatch, fileName)) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // If-Modified-Since header should be greater than LastModified. If so, then return 304. // This header is ignored if any If-None-Match header is specified. long ifModifiedSince = request.getDateHeader("If-Modified-Since"); if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // Validate request headers for resume ---------------------------------------------------- // If-Match header should contain "*" or ETag. If not, then return 412. String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !matches(ifMatch, fileName)) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // If-Unmodified-Since header should be greater than LastModified. If not, then return 412. long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since"); if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // Validate and process range ------------------------------------------------------------- // Prepare some variables. The full Range represents the complete file. Range full = new Range(0, length - 1, length); List<Range> ranges = new ArrayList<>(); // Validate and process Range and If-Range headers. String range = request.getHeader("Range"); if (range != null) { // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416. if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { response.setHeader("Content-Range", "bytes */" + length); // Required in 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(fileName)) { try { long ifRangeTime = request.getDateHeader("If-Range"); // Throws IAE if invalid. if (ifRangeTime != -1) { ranges.add(full); } } catch (IllegalArgumentException ignore) { ranges.add(full); } } // If any valid If-Range header, then process each part of byte range. 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 = length - end; end = length - 1; } else if (end == -1 || end > length - 1) { end = length - 1; } // Check if Range is syntactically valid. If not, then return 416. if (start > end) { response.setHeader("Content-Range", "bytes */" + length); // Required in 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } // Add range. ranges.add(new Range(start, end, length)); } } } // Prepare and initialize response -------------------------------------------------------- // 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(DEFAULT_BUFFER_SIZE); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", fileName); response.setDateHeader("Last-Modified", lastModified); response.setDateHeader("Expires", System.currentTimeMillis() + 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. response.setContentType(contentType); response.setHeader("Content-Range", "bytes " + full.start + "-" + full.end + "/" + full.total); response.setHeader("Content-Length", String.valueOf(full.length)); copy(input, output, length, full.start, full.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, length, r.start, r.length); } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + 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("--" + 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, length, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + MULTIPART_BOUNDARY + "--"); } } finally { // Gently close streams. close(output); close(input); close(dataStream); } }
From source file:com.swingtech.apps.filemgmt.controller.StreamingViewRenderer.java
@Override protected void renderMergedOutputModel(Map objectMap, HttpServletRequest request, HttpServletResponse response) throws Exception { InputStream dataStream = (InputStream) objectMap.get(DownloadConstants.INPUT_STREAM); if (dataStream == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return;//w w w .j a v a2 s .c o m } long length = (Long) objectMap.get(DownloadConstants.CONTENT_LENGTH); String fileName = (String) objectMap.get(DownloadConstants.FILENAME); Date lastModifiedObj = (Date) objectMap.get(DownloadConstants.LAST_MODIFIED); if (StringUtils.isEmpty(fileName) || lastModifiedObj == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } long lastModified = lastModifiedObj.getTime(); String contentType = (String) objectMap.get(DownloadConstants.CONTENT_TYPE); // Validate request headers for caching // --------------------------------------------------- // If-None-Match header should contain "*" or ETag. If so, then return // 304. String ifNoneMatch = request.getHeader("If-None-Match"); if (ifNoneMatch != null && HttpUtils.matches(ifNoneMatch, fileName)) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // If-Modified-Since header should be greater than LastModified. If so, // then return 304. // This header is ignored if any If-None-Match header is specified. long ifModifiedSince = request.getDateHeader("If-Modified-Since"); if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // Validate request headers for resume // ---------------------------------------------------- // If-Match header should contain "*" or ETag. If not, then return 412. String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !HttpUtils.matches(ifMatch, fileName)) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // If-Unmodified-Since header should be greater than LastModified. If // not, then return 412. long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since"); if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // Validate and process range // ------------------------------------------------------------- // Prepare some variables. The full Range represents the complete file. Range full = new Range(0, length - 1, length); List<Range> ranges = new ArrayList<Range>(); // Validate and process Range and If-Range headers. String range = request.getHeader("Range"); if (range != null) { // Range header should match format "bytes=n-n,n-n,n-n...". If not, // then return 416. if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { response.setHeader("Content-Range", "bytes */" + length); // Required // in // 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(fileName)) { try { long ifRangeTime = request.getDateHeader("If-Range"); // Throws // IAE // if // invalid. if (ifRangeTime != -1) { ranges.add(full); } } catch (IllegalArgumentException ignore) { ranges.add(full); } } // If any valid If-Range header, then process each part of byte // range. 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 = StringUtils.sublong(part, 0, part.indexOf("-")); long end = StringUtils.sublong(part, part.indexOf("-") + 1, part.length()); if (start == -1) { start = length - end; end = length - 1; } else if (end == -1 || end > length - 1) { end = length - 1; } // Check if Range is syntactically valid. If not, then // return 416. if (start > end) { response.setHeader("Content-Range", "bytes */" + length); // Required // in // 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } // Add range. ranges.add(new Range(start, end, length)); } } } // Prepare and initialize response // -------------------------------------------------------- // 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 && HttpUtils.accepts(accept, contentType) ? "inline" : "attachment"; } // Initialize response. response.reset(); response.setBufferSize(DEFAULT_BUFFER_SIZE); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", fileName); response.setDateHeader("Last-Modified", lastModified); response.setDateHeader("Expires", System.currentTimeMillis() + 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, length, 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, length, r.start, r.length); } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + 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("--" + 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, length, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + MULTIPART_BOUNDARY + "--"); } } finally { // Gently close streams. close(output); close(input); close(dataStream); } }
From source file:com.harrywu.springweb.common.StreamingViewRenderer.java
@Override public void renderMergedOutputModel(Map<String, Object> objectMap, HttpServletRequest request, HttpServletResponse response) throws Exception { InputStream dataStream = (InputStream) objectMap.get(INPUT_STREAM); if (dataStream == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return;// www .j a v a 2 s.c o m } long length = (Long) objectMap.get(CONTENT_LENGTH); String fileName = (String) objectMap.get(FILENAME); Date lastModifiedObj = (Date) objectMap.get(LAST_MODIFIED); if (StringUtils.isEmpty(fileName) || lastModifiedObj == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } long lastModified = lastModifiedObj.getTime(); String contentType = (String) objectMap.get(CONTENT_TYPE); // Validate request headers for caching // --------------------------------------------------- // If-None-Match header should contain "*" or ETag. If so, then return // 304. String ifNoneMatch = request.getHeader("If-None-Match"); if (ifNoneMatch != null && matches(ifNoneMatch, fileName)) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // If-Modified-Since header should be greater than LastModified. If so, // then return 304. // This header is ignored if any If-None-Match header is specified. long ifModifiedSince = request.getDateHeader("If-Modified-Since"); if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // Validate request headers for resume // ---------------------------------------------------- // If-Match header should contain "*" or ETag. If not, then return 412. String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !matches(ifMatch, fileName)) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // If-Unmodified-Since header should be greater than LastModified. If // not, then return 412. long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since"); if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // Validate and process range // ------------------------------------------------------------- // Prepare some variables. The full Range represents the complete file. Range full = new Range(0, length - 1, length); List<Range> ranges = new ArrayList<Range>(); // Validate and process Range and If-Range headers. String range = request.getHeader("Range"); if (range != null) { // Range header should match format "bytes=n-n,n-n,n-n...". If not, // then return 416. if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { response.setHeader("Content-Range", "bytes */" + length); // Required // in // 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(fileName)) { try { long ifRangeTime = request.getDateHeader("If-Range"); // Throws // IAE // if // invalid. if (ifRangeTime != -1) { ranges.add(full); } } catch (IllegalArgumentException ignore) { ranges.add(full); } } // If any valid If-Range header, then process each part of byte // range. 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 = length - end; end = length - 1; } else if (end == -1 || end > length - 1) { end = length - 1; } // Check if Range is syntactically valid. If not, then // return 416. if (start > end) { response.setHeader("Content-Range", "bytes */" + length); // Required // in // 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } // Add range. ranges.add(new Range(start, end, length)); } } } // Prepare and initialize response // -------------------------------------------------------- // 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(DEFAULT_BUFFER_SIZE); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", fileName); response.setDateHeader("Last-Modified", lastModified); response.setDateHeader("Expires", System.currentTimeMillis() + 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, length, 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, length, r.start, r.length); } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + 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("--" + 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, length, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + MULTIPART_BOUNDARY + "--"); } } finally { // Gently close streams. close(output); close(input); close(dataStream); } }
From source file:com.sastix.cms.server.utils.MultipartFileSender.java
public void serveResource() throws Exception { if (response == null || request == null) { return;/*from w w w . ja va 2s . c o m*/ } Long length = Files.size(filepath); String fileName = filepath.getFileName().toString(); FileTime lastModifiedObj = Files.getLastModifiedTime(filepath); if (StringUtils.isEmpty(fileName) || lastModifiedObj == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } long lastModified = LocalDateTime .ofInstant(lastModifiedObj.toInstant(), ZoneId.of(ZoneOffset.systemDefault().getId())) .toEpochSecond(ZoneOffset.UTC); // Validate request headers for caching --------------------------------------------------- // If-None-Match header should contain "*" or ETag. If so, then return 304. String ifNoneMatch = request.getHeader("If-None-Match"); if (ifNoneMatch != null && HttpUtils.matches(ifNoneMatch, fileName)) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // If-Modified-Since header should be greater than LastModified. If so, then return 304. // This header is ignored if any If-None-Match header is specified. long ifModifiedSince = request.getDateHeader("If-Modified-Since"); if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) { response.setHeader("ETag", fileName); // Required in 304. response.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } // Validate request headers for resume ---------------------------------------------------- // If-Match header should contain "*" or ETag. If not, then return 412. String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !HttpUtils.matches(ifMatch, fileName)) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // If-Unmodified-Since header should be greater than LastModified. If not, then return 412. long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since"); if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) { response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); return; } // Validate and process range ------------------------------------------------------------- // Prepare some variables. The full Range represents the complete file. Range full = new Range(0, length - 1, length); List<Range> ranges = new ArrayList<>(); // Validate and process Range and If-Range headers. String range = request.getHeader("Range"); if (range != null) { // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416. if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { response.setHeader("Content-Range", "bytes */" + length); // Required in 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(fileName)) { try { long ifRangeTime = request.getDateHeader("If-Range"); // Throws IAE if invalid. if (ifRangeTime != -1) { ranges.add(full); } } catch (IllegalArgumentException ignore) { ranges.add(full); } } // If any valid If-Range header, then process each part of byte range. 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 = Range.sublong(part, 0, part.indexOf("-")); long end = Range.sublong(part, part.indexOf("-") + 1, part.length()); if (start == -1) { start = length - end; end = length - 1; } else if (end == -1 || end > length - 1) { end = length - 1; } // Check if Range is syntactically valid. If not, then return 416. if (start > end) { response.setHeader("Content-Range", "bytes */" + length); // Required in 416. response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } // Add range. ranges.add(new Range(start, end, length)); } } } // Prepare and initialize response -------------------------------------------------------- // 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 && HttpUtils.accepts(accept, contentType) ? "inline" : "attachment"; } LOG.debug("Content-Type : {}", contentType); // Initialize response. response.reset(); response.setBufferSize(DEFAULT_BUFFER_SIZE); response.setHeader("Content-Type", contentType); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); LOG.debug("Content-Disposition : {}", disposition); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", fileName); response.setDateHeader("Last-Modified", lastModified); response.setDateHeader("Expires", System.currentTimeMillis() + DEFAULT_EXPIRE_TIME); // Send requested file (part(s)) to client ------------------------------------------------ // Prepare streams. try (InputStream input = new BufferedInputStream(Files.newInputStream(filepath)); OutputStream output = response.getOutputStream()) { if (ranges.isEmpty() || ranges.get(0) == full) { // Return full file. LOG.debug("Return full file"); response.setContentType(contentType); response.setHeader("Content-Range", "bytes " + full.start + "-" + full.end + "/" + full.total); response.setHeader("Content-Length", String.valueOf(full.length)); Range.copy(input, output, length, full.start, full.length); } else if (ranges.size() == 1) { // Return single part of file. Range r = ranges.get(0); LOG.debug("Return 1 part of file : from ({}) to ({})", r.start, r.end); 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. Range.copy(input, output, length, r.start, r.length); } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + 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) { LOG.debug("Return multi part of file : from ({}) to ({})", r.start, r.end); // Add multipart boundary and header fields for every range. sos.println(); sos.println("--" + 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. Range.copy(input, output, length, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + MULTIPART_BOUNDARY + "--"); } } }
From source file:org.alfresco.repo.web.util.HttpRangeProcessor.java
/** * Process a single range request.//from w w w . ja v a 2 s .co m * * @param res HttpServletResponse * @param reader ContentReader to retrieve content * @param range Range header value * @param mimetype Content mimetype * * @return true if processed range, false otherwise */ private boolean processSingleRange(Object res, ContentReader reader, String range, String mimetype) throws IOException { // Handle either HttpServletResponse or WebScriptResponse HttpServletResponse httpServletResponse = null; WebScriptResponse webScriptResponse = null; if (res instanceof HttpServletResponse) { httpServletResponse = (HttpServletResponse) res; } else if (res instanceof WebScriptResponse) { webScriptResponse = (WebScriptResponse) res; } if (httpServletResponse == null && webScriptResponse == null) { // Unknown response object type return false; } // return the specific set of bytes as requested in the content-range header /* Examples of byte-content-range-spec values, assuming that the entity contains total of 1234 bytes: The first 500 bytes: bytes 0-499/1234 The second 500 bytes: bytes 500-999/1234 All except for the first 500 bytes: bytes 500-1233/1234 */ /* 'Range' header example: bytes=10485760-20971519 */ boolean processedRange = false; Range r = null; try { r = Range.constructRange(range, mimetype, reader.getSize()); } catch (IllegalArgumentException err) { if (getLogger().isDebugEnabled()) getLogger().debug("Failed to parse range header - returning 416 status code: " + err.getMessage()); if (httpServletResponse != null) { httpServletResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); httpServletResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\""); httpServletResponse.getOutputStream().close(); } else if (webScriptResponse != null) { webScriptResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); webScriptResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\""); webScriptResponse.getOutputStream().close(); } return true; } // set Partial Content status and range headers String contentRange = "bytes " + Long.toString(r.start) + "-" + Long.toString(r.end) + "/" + Long.toString(reader.getSize()); if (httpServletResponse != null) { httpServletResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); httpServletResponse.setContentType(mimetype); httpServletResponse.setHeader(HEADER_CONTENT_RANGE, contentRange); httpServletResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString((r.end - r.start) + 1L)); } else if (webScriptResponse != null) { webScriptResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); webScriptResponse.setContentType(mimetype); webScriptResponse.setHeader(HEADER_CONTENT_RANGE, contentRange); webScriptResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString((r.end - r.start) + 1L)); } if (getLogger().isDebugEnabled()) getLogger().debug("Processing: Content-Range: " + contentRange); InputStream is = null; try { // output the binary data for the range OutputStream os = null; if (httpServletResponse != null) { os = httpServletResponse.getOutputStream(); } else if (webScriptResponse != null) { os = webScriptResponse.getOutputStream(); } is = reader.getContentInputStream(); streamRangeBytes(r, is, os, 0L); os.close(); processedRange = true; } catch (IOException err) { if (getLogger().isDebugEnabled()) getLogger().debug("Unable to process single range due to IO Exception: " + err.getMessage()); throw err; } finally { if (is != null) is.close(); } return processedRange; }