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:org.mycore.common.content.util.MCRServletContentHelper.java
/** * Parses and validates the range header. * This method ensures that all ranges are in ascending order and non-overlapping, so we can use a single * InputStream.// w w w . j a v a2 s .c om */ private static ArrayList<Range> parseRange(final HttpServletRequest request, final HttpServletResponse response, final MCRContent content) throws IOException { // Checking if range is still valid (lastModified) final String headerValue = request.getHeader("If-Range"); if (headerValue != null) { long headerValueTime = -1L; try { headerValueTime = request.getDateHeader("If-Range"); } catch (final IllegalArgumentException e) { // Ignore } final String eTag = content.getETag(); final long lastModified = content.lastModified(); if (headerValueTime == -1L) { // If the content changed, the complete content is served. if (!eTag.equals(headerValue.trim())) { return FULL; } } else { //add one second buffer to check if the content was modified. if (lastModified > headerValueTime + 1000) { return FULL; } } } final long fileLength = content.length(); if (fileLength <= 0) { return null; } String rangeHeader = request.getHeader("Range"); if (rangeHeader == null) { return null; } // We operate on byte level only String rangeUnit = "bytes"; if (!rangeHeader.startsWith(rangeUnit)) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } rangeHeader = rangeHeader.substring(rangeUnit.length() + 1); final ArrayList<Range> result = new ArrayList<>(); final StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list long lastByte = 0; while (commaTokenizer.hasMoreTokens()) { final String rangeDefinition = commaTokenizer.nextToken().trim(); final Range currentRange = new Range(); currentRange.length = fileLength; final int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (dashPos == 0) { try { //offset is negative final long offset = Long.parseLong(rangeDefinition); currentRange.start = fileLength + offset; currentRange.end = fileLength - 1; } catch (final NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } else { try { currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos)); if (dashPos < rangeDefinition.length() - 1) { currentRange.end = Long .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length())); } else { currentRange.end = fileLength - 1; } } catch (final NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } if (!currentRange.validate() || lastByte > currentRange.start) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } lastByte = currentRange.end; result.add(currentRange); } return result; }
From source file:org.openhab.ui.cometvisu.internal.servlet.CometVisuServlet.java
/** * Process the actual request./*from ww w .ja va2 s . c o m*/ * * @param request * The request to be processed. * @param response * The response to be created. * @param content * Whether the request body should be written (GET) or not * (HEAD). * @throws IOException * If something fails at I/O level. * * @author BalusC * @link * http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and * .html */ private void processStaticRequest(File file, HttpServletRequest request, HttpServletResponse response, boolean content) throws IOException { // Validate the requested file // ------------------------------------------------------------ if (file == null) { // Get requested file by path info. String requestedFile = request.getPathInfo(); // Check if file is actually supplied to the request URL. if (requestedFile == null) { // Do your thing if the file is not supplied to the request URL. // Throw an exception, or send 404, or show default/warning // page, or // just ignore it. response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } // URL-decode the file name (might contain spaces and on) and // prepare // file object. file = new File(rootFolder, URLDecoder.decode(requestedFile, "UTF-8")); } if (file.equals(rootFolder) || (file.exists() && file.isDirectory())) { file = new File(file, "index.html"); } // Check if file actually exists in filesystem. if (!file.exists()) { // show installation hints if the CometVisu-Clients main index.html is requested but cannot be found if (file.getParentFile().equals(rootFolder) && (file.getName().equalsIgnoreCase("index.html") || file.getName().length() == 0)) { // looking for CometVisu clients index.html file String path = null; File folder = file.isDirectory() ? file : file.getParentFile(); if (folder.exists()) { File index = ClientInstaller.findClientRoot(folder, "index.html"); path = index.exists() ? index.getPath().replaceFirst(rootFolder.getPath() + "/", "") : null; } if (path != null) { // forward to position response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); response.setHeader("Location", path + "?" + request.getQueryString()); } else { showInstallationHint(request, response); } } else { response.sendError(HttpServletResponse.SC_NOT_FOUND); } return; } // Prepare some variables. The ETag is an unique identifier of the file. String fileName = file.getName(); long length = file.length(); long lastModified = file.lastModified(); String eTag = fileName + "_" + length + "_" + lastModified; long expires = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME; // 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, eTag)) { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); response.setHeader("ETag", eTag); // Required in 304. response.setDateHeader("Expires", expires); // Postpone cache with 1 // week. 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.setStatus(HttpServletResponse.SC_NOT_MODIFIED); response.setHeader("ETag", eTag); // Required in 304. response.setDateHeader("Expires", expires); // Postpone cache with 1 // week. 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, eTag)) { 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; } // If-Range header should either match ETag or be greater then // LastModified. If not, // then return full file. String ifRange = request.getHeader("If-Range"); if (ifRange != null && !ifRange.equals(eTag)) { try { long ifRangeTime = request.getDateHeader("If-Range"); // Throws // IAE // if // invalid. if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) { 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 default GZIP support and // content disposition. String contentType = getServletContext().getMimeType(fileName); boolean acceptsGzip = false; 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"; } // If content type is text, then determine whether GZIP content encoding // is supported by // the browser and expand content type with the one and right character // encoding. if (contentType.startsWith("text")) { String acceptEncoding = request.getHeader("Accept-Encoding"); acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip"); contentType += ";charset=UTF-8"; } // 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. else if (!contentType.startsWith("image")) { String accept = request.getHeader("Accept"); disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment"; } response.setBufferSize(DEFAULT_BUFFER_SIZE); response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\""); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", eTag); response.setDateHeader("Last-Modified", lastModified); response.setDateHeader("Expires", expires); // Send requested file (part(s)) to client // ------------------------------------------------ // Prepare streams. RandomAccessFile input = null; OutputStream output = null; try { // Open streams. input = new RandomAccessFile(file, "r"); 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); if (content) { if (acceptsGzip) { // The browser accepts GZIP, so GZIP the content. response.setHeader("Content-Encoding", "gzip"); output = new GZIPOutputStream(output, DEFAULT_BUFFER_SIZE); } else { // Content length is not directly predictable in case of // GZIP. // So only add it if there is no means of GZIP, else // browser will hang. response.setHeader("Content-Length", String.valueOf(r.length)); } // Copy full range. copy(input, output, 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. if (content) { // Copy single part range. copy(input, output, r.start, r.length); } } else { // Return multiple parts of file. response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206. if (content) { // 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, r.start, r.length); } // End with multipart boundary. sos.println(); sos.println("--" + MULTIPART_BOUNDARY + "--"); } } } finally { // Gently close streams. close(output); close(input); } }
From source file:org.apache.catalina.servlets.DefaultServlet.java
/** * Parse the range header./*from www . j a v a 2 s . c o m*/ * * @param request The servlet request we are processing * @param response The servlet response we are creating * @param resourceInfo Description of the Parameter * @return Vector of ranges * @throws IOException Description of the Exception */ protected Vector parseRange(HttpServletRequest request, HttpServletResponse response, ResourceInfo resourceInfo) throws IOException { // Checking If-Range String headerValue = request.getHeader("If-Range"); if (headerValue != null) { long headerValueTime = (-1L); try { headerValueTime = request.getDateHeader("If-Range"); } catch (Exception e) { ; } String eTag = getETag(resourceInfo); long lastModified = resourceInfo.date; if (headerValueTime == (-1L)) { // If the ETag the client gave does not match the entity // etag, then the entire entity is returned. if (!eTag.equals(headerValue.trim())) { return null; } } else { // If the timestamp of the entity the client got is older than // the last modification date of the entity, the entire entity // is returned. if (lastModified > (headerValueTime + 1000)) { return null; } } } long fileLength = resourceInfo.length; if (fileLength == 0) { return null; } // Retrieving the range header (if any is specified String rangeHeader = request.getHeader("Range"); if (rangeHeader == null) { return null; } // bytes is the only range unit supported (and I don't see the point // of adding new ones). if (!rangeHeader.startsWith("bytes")) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } rangeHeader = rangeHeader.substring(6); // Vector which will contain all the ranges which are successfully // parsed. Vector result = new Vector(); StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list while (commaTokenizer.hasMoreTokens()) { String rangeDefinition = commaTokenizer.nextToken().trim(); Range currentRange = new Range(); currentRange.length = fileLength; int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (dashPos == 0) { try { long offset = Long.parseLong(rangeDefinition); currentRange.start = fileLength + offset; currentRange.end = fileLength - 1; } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } else { try { currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos)); if (dashPos < rangeDefinition.length() - 1) { currentRange.end = Long .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length())); } else { currentRange.end = fileLength - 1; } } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } if (!currentRange.validate()) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } result.addElement(currentRange); } return result; }
From source file:org.opencms.webdav.CmsWebdavServlet.java
/** * Parse the range header.<p>/*from w w w .j av a2s .c o m*/ * * @param request the servlet request we are processing * @param response the servlet response we are creating * @param item the WebdavItem with the information * * @return Vector of ranges */ protected ArrayList<CmsWebdavRange> parseRange(HttpServletRequest request, HttpServletResponse response, I_CmsRepositoryItem item) { // Checking If-Range String headerValue = request.getHeader(HEADER_IFRANGE); if (headerValue != null) { long headerValueTime = (-1L); try { headerValueTime = request.getDateHeader(HEADER_IFRANGE); } catch (Exception e) { // noop } String eTag = getETag(item); long lastModified = item.getLastModifiedDate(); if (headerValueTime == (-1L)) { // If the ETag the client gave does not match the entity // etag, then the entire entity is returned. if (!eTag.equals(headerValue.trim())) { return FULL_RANGE; } } else { // If the timestamp of the entity the client got is older than // the last modification date of the entity, the entire entity // is returned. if (lastModified > (headerValueTime + 1000)) { return FULL_RANGE; } } } long fileLength = item.getContentLength(); if (fileLength == 0) { return null; } // Retrieving the range header (if any is specified String rangeHeader = request.getHeader(HEADER_RANGE); if (rangeHeader == null) { return null; } // bytes is the only range unit supported (and I don't see the point // of adding new ones). if (!rangeHeader.startsWith("bytes")) { response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } rangeHeader = rangeHeader.substring(6); // Vector which will contain all the ranges which are successfully parsed. ArrayList<CmsWebdavRange> result = new ArrayList<CmsWebdavRange>(); StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list while (commaTokenizer.hasMoreTokens()) { String rangeDefinition = commaTokenizer.nextToken().trim(); CmsWebdavRange currentRange = new CmsWebdavRange(); currentRange.setLength(fileLength); int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) { response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (dashPos == 0) { try { long offset = Long.parseLong(rangeDefinition); currentRange.setStart(fileLength + offset); currentRange.setEnd(fileLength - 1); } catch (NumberFormatException e) { response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } else { try { currentRange.setStart(Long.parseLong(rangeDefinition.substring(0, dashPos))); if (dashPos < (rangeDefinition.length() - 1)) { currentRange.setEnd( Long.parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()))); } else { currentRange.setEnd(fileLength - 1); } } catch (NumberFormatException e) { response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } if (!currentRange.validate()) { response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength); response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } result.add(currentRange); } return result; }
From source file:org.gss_project.gss.server.rest.Webdav.java
/** * Parse the range header.//from w ww .j a v a2s .com * * @param request The servlet request we are processing * @param response The servlet response we are creating * @param file * @param oldBody the old version of the file, if requested * @return Vector of ranges * @throws IOException */ protected ArrayList parseRange(HttpServletRequest request, HttpServletResponse response, FileHeader file, FileBody oldBody) throws IOException { // Checking If-Range String headerValue = request.getHeader("If-Range"); if (headerValue != null) { long headerValueTime = -1L; try { headerValueTime = request.getDateHeader("If-Range"); } catch (IllegalArgumentException e) { // Do nothing. } String eTag = getETag(file, oldBody); long lastModified = oldBody == null ? file.getAuditInfo().getModificationDate().getTime() : oldBody.getAuditInfo().getModificationDate().getTime(); if (headerValueTime == -1L) { // If the ETag the client gave does not match the entity // etag, then the entire entity is returned. if (!eTag.equals(headerValue.trim())) return FULL; } else // If the timestamp of the entity the client got is older than // the last modification date of the entity, the entire entity // is returned. if (lastModified > headerValueTime + 1000) return FULL; } long fileLength = oldBody == null ? file.getCurrentBody().getFileSize() : oldBody.getFileSize(); if (fileLength == 0) return null; // Retrieving the range header (if any is specified). String rangeHeader = request.getHeader("Range"); if (rangeHeader == null) return null; // bytes is the only range unit supported (and I don't see the point // of adding new ones). if (!rangeHeader.startsWith("bytes")) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } rangeHeader = rangeHeader.substring(6); // Vector that will contain all the ranges which are successfully // parsed. ArrayList<Range> result = new ArrayList<Range>(); StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list while (commaTokenizer.hasMoreTokens()) { String rangeDefinition = commaTokenizer.nextToken().trim(); Range currentRange = new Range(); currentRange.length = fileLength; int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (dashPos == 0) try { long offset = Long.parseLong(rangeDefinition); currentRange.start = fileLength + offset; currentRange.end = fileLength - 1; } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } else try { currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos)); if (dashPos < rangeDefinition.length() - 1) currentRange.end = Long .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length())); else currentRange.end = fileLength - 1; } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (!currentRange.validate()) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } result.add(currentRange); } return result; }
From source file:de.innovationgate.wgpublisher.WGPDispatcher.java
/** * writes the given data to the response based on response.getContentType() * either reader/writer (for textual content) or binary streams are used * /*from w w w. j ava 2s . com*/ * @param data * - the data as inputstream to write - implicit closed after * method call * @param request * @param response * @param characterEncoding * - encoding to use when reading character based from given * data, if null platform encoding is used * @throws IOException * @throws HttpErrorException */ private void writeData(DataSource data, HttpServletRequest request, HttpServletResponse response, String characterEncoding, long size, String sourceHint, boolean allowRequestRanges) throws IOException, HttpErrorException { // Parse accept ranges if requested List<AcceptRange> ranges = new ArrayList<AcceptRange>(); String rangeHeader = request.getHeader("Range"); if (rangeHeader != null && allowRequestRanges && size > 0) { if (rangeHeader.startsWith("bytes=")) { rangeHeader = rangeHeader.substring("bytes=".length()); String[] subranges = rangeHeader.split("\\s*,\\s*"); for (String r : subranges) { Matcher matcher = ACCEPT_RANGE_PATTERN.matcher(r); if (matcher.matches()) { String from = matcher.group(1); String to = matcher.group(2); AcceptRange newRange; try { newRange = new AcceptRange(from != null ? Integer.parseInt(from) : -1, to != null ? Integer.parseInt(to) : -1); if (newRange.from == -1) { newRange.from = size - newRange.to; newRange.to = size - 1; } else if (newRange.to == -1) { newRange.to = size - 1; } } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + size); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } if ((newRange.from == -1 && newRange.to == -1) || newRange.to > size) { response.addHeader("Content-Range", "bytes */" + size); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } ranges.add(newRange); } else { response.addHeader("Content-Range", "bytes */" + size); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } } } else { response.addHeader("Content-Range", "bytes */" + size); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return; } } if (ranges.isEmpty()) { // We can only set the raw length on binary resources bc. // transcoding textual response can change the size if (isBinary(request, response) && size > 0) { response.setContentLength((new Long(size)).intValue()); } if (!"HEAD".equalsIgnoreCase(request.getMethod())) { writeWholeData(data, request, response, characterEncoding, sourceHint); } } else { response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); if (ranges.size() == 1) { AcceptRange r = ranges.get(0); response.addHeader("Content-Range", "bytes " + r.from + "-" + r.to + "/" + size); response.setContentLength((new Long(r.to - r.from + 1)).intValue()); } else { response.setContentType("multipart/byteranges; boundary=" + BYTERANGE_BOUNDARY); } if (!"HEAD".equalsIgnoreCase(request.getMethod())) { writeRangesData(data, ranges, response, sourceHint, size); } } }
From source file:org.sakaiproject.content.impl.BaseContentService.java
/** * Parse the range header.//w w w. java 2s. com * * @param request The servlet request we are processing * @param response The servlet response we are creating * @return Vector of ranges */ protected ArrayList<Range> parseRange(HttpServletRequest request, HttpServletResponse response, long fileLength) throws IOException { /* Commented out pending implementation of last-modified / if-modified. * See http://jira.sakaiproject.org/jira/browse/SAK-3916 // Checking If-Range String headerValue = request.getHeader("If-Range"); if (headerValue != null) { long headerValueTime = (-1L); try { headerValueTime = request.getDateHeader("If-Range"); } catch (Exception e) { ; } String eTag = getETag(resourceAttributes); long lastModified = resourceAttributes.getLastModified(); if (headerValueTime == (-1L)) { // If the ETag the client gave does not match the entity // etag, then the entire entity is returned. if (!eTag.equals(headerValue.trim())) return FULL; } else { // If the timestamp of the entity the client got is older than // the last modification date of the entity, the entire entity // is returned. if (lastModified > (headerValueTime + 1000)) return FULL; } } */ if (fileLength == 0) return null; // Retrieving the range header (if any is specified String rangeHeader = request.getHeader("Range"); if (rangeHeader == null) return null; // bytes is the only range unit supported (and I don't see the point // of adding new ones). if (!rangeHeader.startsWith("bytes")) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } rangeHeader = rangeHeader.substring(6); // Vector which will contain all the ranges which are successfully // parsed. ArrayList result = new ArrayList(); StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list while (commaTokenizer.hasMoreTokens()) { String rangeDefinition = commaTokenizer.nextToken().trim(); Range currentRange = new Range(); currentRange.length = fileLength; int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } if (dashPos == 0) { try { long offset = Long.parseLong(rangeDefinition); currentRange.start = fileLength + offset; currentRange.end = fileLength - 1; } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } else { try { currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos)); if (dashPos < rangeDefinition.length() - 1) currentRange.end = Long .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length())); else currentRange.end = fileLength - 1; } catch (NumberFormatException e) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } } if (!currentRange.validate()) { response.addHeader("Content-Range", "bytes */" + fileLength); response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); return null; } result.add(currentRange); } return result; }