List of usage examples for javax.servlet.http HttpServletResponse SC_PARTIAL_CONTENT
int SC_PARTIAL_CONTENT
To view the source code for javax.servlet.http HttpServletResponse SC_PARTIAL_CONTENT.
Click Source Link
From source file:org.sakaiproject.tool.assessment.ui.servlet.delivery.ShowMediaServlet.java
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String agentIdString = getAgentString(req, res); if (agentIdString == null) { String path = "/jsf/delivery/mediaAccessDenied.faces"; RequestDispatcher dispatcher = req.getRequestDispatcher(path); dispatcher.forward(req, res);/* ww w . j a v a 2 s. c om*/ return; } String mediaId = req.getParameter("mediaId"); if (mediaId == null || mediaId.trim().equals("")) { return; } // get media GradingService gradingService = new GradingService(); MediaData mediaData = gradingService.getMedia(mediaId); String mediaLocation = mediaData.getLocation(); int fileSize = mediaData.getFileSize().intValue(); log.info("****1. media file size=" + fileSize); //if setMimeType="false" in query string, implies, we want to do a forced download //in this case, we set contentType='application/octet-stream' String setMimeType = req.getParameter("setMimeType"); log.info("****2. setMimeType=" + setMimeType); // get assessment's ownerId // String assessmentCreatedBy = req.getParameter("createdBy"); // who can access the media? You can, // a. if you are the creator. // b. if you have a assessment.grade.any or assessment.grade.own permission boolean accessDenied = true; String currentSiteId = ""; boolean isAudio = false; Long assessmentGradingId = mediaData.getItemGradingData().getAssessmentGradingId(); PublishedAssessmentIfc pub = gradingService .getPublishedAssessmentByAssessmentGradingId(assessmentGradingId.toString()); if (pub != null) { PublishedAssessmentService service = new PublishedAssessmentService(); currentSiteId = service.getPublishedAssessmentOwner(pub.getPublishedAssessmentId()); } // some log checking //log.debug("agentIdString ="+agentIdString); //log.debug("****current site Id ="+currentSiteId); boolean hasPrivilege = agentIdString != null && (agentIdString.equals(mediaData.getCreatedBy()) // user is creator || canGrade(req, res, agentIdString, currentSiteId)); if (hasPrivilege) { accessDenied = false; } if (accessDenied) { String path = "/jsf/delivery/mediaAccessDenied.faces"; RequestDispatcher dispatcher = req.getRequestDispatcher(path); dispatcher.forward(req, res); } else { String displayType = "inline"; if (mediaData.getMimeType() != null && !mediaData.getMimeType().equals("application/octet-stream") && !(setMimeType != null && ("false").equals(setMimeType))) { res.setContentType(mediaData.getMimeType()); } else { displayType = "attachment"; res.setContentType("application/octet-stream"); } log.debug("****" + displayType + ";filename=\"" + mediaData.getFilename() + "\";"); res.setHeader("Content-Disposition", displayType + ";filename=\"" + mediaData.getFilename() + "\";"); int start = 0; int end = fileSize - 1; int rangeContentLength = end - start + 1; String range = req.getHeader("Range"); if (StringUtils.isNotBlank(range)) { Matcher matcher = HTTP_RANGE_PATTERN.matcher(range); if (matcher.matches()) { String startMatch = matcher.group(1); start = startMatch.isEmpty() ? start : Integer.valueOf(startMatch); start = start < 0 ? 0 : start; String endMatch = matcher.group(2); end = endMatch.isEmpty() ? end : Integer.valueOf(endMatch); end = end > fileSize - 1 ? fileSize - 1 : end; rangeContentLength = end - start + 1; } res.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, fileSize)); res.setHeader("Content-Length", String.format("%s", rangeContentLength)); res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); } else { res.setContentLength(fileSize); } //** note that res.setContentType() must be called before res.getOutputStream(). see javadoc on this FileInputStream inputStream = null; BufferedInputStream buf_inputStream = null; ServletOutputStream outputStream = res.getOutputStream(); BufferedOutputStream buf_outputStream = null; ByteArrayInputStream byteArrayInputStream = null; if (mediaLocation == null || (mediaLocation.trim()).equals("")) { try { byteArrayInputStream = new ByteArrayInputStream(mediaData.getMedia()); buf_inputStream = new BufferedInputStream(byteArrayInputStream); } catch (Exception e) { log.error("****empty media save to DB=" + e.getMessage()); } } else { try { inputStream = getFileStream(mediaLocation); buf_inputStream = new BufferedInputStream(inputStream); } catch (Exception e) { log.error("****empty media save to file =" + e.getMessage()); } } try { buf_outputStream = new BufferedOutputStream(outputStream); int i = 0; if (buf_inputStream != null) { // skip to the start of the possible range request buf_inputStream.skip(start); int bytesLeft = rangeContentLength; byte[] buffer = new byte[1024]; while ((i = buf_inputStream.read(buffer)) != -1 && bytesLeft > 0) { buf_outputStream.write(buffer); bytesLeft -= i; } } log.debug("**** mediaLocation=" + mediaLocation); res.flushBuffer(); } catch (Exception e) { log.warn(e.getMessage()); } finally { if (buf_outputStream != null) { try { buf_outputStream.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (buf_inputStream != null) { try { buf_inputStream.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (byteArrayInputStream != null) { try { byteArrayInputStream.close(); } catch (IOException e) { log.error(e.getMessage()); } } } } }
From source file:net.ymate.platform.mvc.web.view.impl.BinaryView.java
private void __doSetRangeHeader(HttpServletRequest request, HttpServletResponse response, PairObject<Long, Long> range) { // none???// ww w. ja va 2 s.c om response.setHeader("Accept-Ranges", "bytes"); // Content-Length: [?] - [?] long _totalLength = range.getValue() - range.getKey(); response.setHeader("Content-Length", _totalLength + ""); // Content-Range: bytes [?]-[? - 1]/[?] response.setHeader("Content-Range", "bytes " + range.getKey() + "-" + (range.getValue() - 1) + "/" + maxLength); // response.setHeader("Connection", "Close"); //???IE // Status: 206 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); }
From source file:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_process_request_plain_one_range() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=0-5"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals("AaBbCc", mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_PARTIAL_CONTENT, mockHttpServletResponse.getStatus()); assertEquals("application/pdf", mockHttpServletResponse.getContentType()); assertEquals("inline;filename=\"input.dat\"", mockHttpServletResponse.getHeader(HttpHeaders.CONTENT_DISPOSITION)); assertEquals("6", mockHttpServletResponse.getHeader(HttpHeaders.CONTENT_LENGTH)); }
From source file:org.alfresco.repo.web.util.HttpRangeProcessor.java
/** * Process a single range request./*from w w w . j a v a2 s .c o 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; }
From source file:org.dspace.app.rest.utils.MultipartFileSender.java
public void serveResource() throws IOException { // Validate and process range ------------------------------------------------------------- // Prepare some variables. The full Range represents the complete file. Range full = getFullRange();// w ww .j a va 2 s . c om List<Range> ranges = getRanges(full); if (ranges == null) { //The supplied range values were invalid return; } log.debug("Content-Type : {}", contentType); // Initialize response. response.reset(); response.setBufferSize(bufferSize); response.setHeader(CONTENT_TYPE, contentType); response.setHeader(ACCEPT_RANGES, BYTES); response.setHeader(ETAG, checksum); response.setDateHeader(LAST_MODIFIED, lastModified); response.setDateHeader(EXPIRES, System.currentTimeMillis() + DEFAULT_EXPIRE_TIME); //No-cache so that we can log every download response.setHeader(CACHE_CONTROL, CACHE_CONTROL_SETTING); if (isNullOrEmpty(disposition)) { if (contentType == null) { contentType = APPLICATION_OCTET_STREAM; } else if (!contentType.startsWith(IMAGE)) { String accept = request.getHeader(ACCEPT); disposition = accept != null && accepts(accept, contentType) ? CONTENT_DISPOSITION_INLINE : CONTENT_DISPOSITION_ATTACHMENT; } response.setHeader(CONTENT_DISPOSITION, String.format(CONTENT_DISPOSITION_FORMAT, disposition, fileName)); log.debug("Content-Disposition : {}", disposition); } // Content phase if (METHOD_HEAD.equals(request.getMethod())) { log.debug("HEAD request - skipping content"); return; } // Send requested file (part(s)) to client ------------------------------------------------ // Prepare streams. try (OutputStream output = response.getOutputStream()) { if (hasNoRanges(full, ranges)) { // Return full file. log.debug("Return full file"); response.setContentType(contentType); response.setHeader(CONTENT_LENGTH, String.valueOf(length)); Range.copy(inputStream, output, length, 0, length, bufferSize); } 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, String.format(BYTES_RANGE_FORMAT, 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(inputStream, output, length, r.start, r.length, bufferSize); } else { // Return multiple parts of file. response.setContentType(CONTENT_TYPE_MULTITYPE_WITH_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("--" + MULTIPART_BOUNDARY); sos.println(CONTENT_TYPE + ": " + contentType); sos.println(CONTENT_RANGE + ": " + String.format(BYTES_RANGE_FORMAT, r.start, r.end, r.total)); //Mark position of inputstream so we can return to it later inputStream.mark(0); // Copy single part range of multi part range. Range.copy(inputStream, output, length, r.start, r.length, bufferSize); inputStream.reset(); sos.println(); } // End with multipart boundary. sos.println("--" + MULTIPART_BOUNDARY + "--"); } } }
From source file:com.epam.catgenome.controller.util.MultipartFileSender.java
public void serveResource() throws IOException { if (response == null || request == null) { return;/*from w ww .ja v a2s .c om*/ } if (!Files.exists(filepath)) { logger.error("File doesn't exist at URI : {}", filepath.toAbsolutePath().toString()); response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } 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); //String contentType = MimeTypeUtils.probeContentType(filepath); String contentType = null; // Validate request headers for caching --------------------------------------------------- if (!validateHeadersCaching(fileName, lastModified)) { return; } // Validate request headers for resume ---------------------------------------------------- if (!validateHeadersResume(fileName, lastModified)) { return; } // Validate and process range ------------------------------------------------------------- Range full = new Range(0, length - 1, length); List<Range> ranges = processRange(length, fileName, full); if (ranges == null) { return; } // 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"; } logger.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 + "\""); logger.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. logger.info("Return full file"); response.setContentType(contentType); response.setHeader(CONTENT_RANGE_HEADER, "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); logger.info("Return 1 part of file : from ({}) to ({})", r.start, r.end); response.setContentType(contentType); response.setHeader(CONTENT_RANGE_HEADER, "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) { logger.info("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:com.enonic.cms.framework.util.HttpServletRangeUtilTest.java
@Test public void test_process_request_multipart_three_ranges() throws Exception { final MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); httpServletRequest.setMethod("GET"); httpServletRequest.setPathInfo("/input.dat"); httpServletRequest.addHeader(HttpHeaders.RANGE, "bytes=0-5,6-10,11-20"); final MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); HttpServletRangeUtil.processRequest(httpServletRequest, mockHttpServletResponse, "input.dat", "application/pdf", INPUT_FILE, false); assertEquals(readFromFile("response3.dat"), mockHttpServletResponse.getContentAsString()); assertEquals(HttpServletResponse.SC_PARTIAL_CONTENT, mockHttpServletResponse.getStatus()); assertEquals("multipart/byteranges; boundary=THIS_STRING_SEPARATES", mockHttpServletResponse.getContentType()); assertEquals("attachment;filename=\"input.dat\"", mockHttpServletResponse.getHeader(HttpHeaders.CONTENT_DISPOSITION)); }
From source file:com.metamesh.opencms.rfs.RfsAwareDumpLoader.java
/** * @see org.opencms.loader.I_CmsResourceLoader#load(org.opencms.file.CmsObject, org.opencms.file.CmsResource, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) *//* w w w .j av a 2s. c o m*/ public void load(CmsObject cms, CmsResource resource, HttpServletRequest req, HttpServletResponse res) throws IOException, CmsException { if (!(resource instanceof RfsCmsResource)) { super.load(cms, resource, req, res); return; } if (canSendLastModifiedHeader(resource, req, res)) { // no further processing required return; } if (CmsWorkplaceManager.isWorkplaceUser(req)) { // prevent caching for Workplace users res.setDateHeader(CmsRequestUtil.HEADER_LAST_MODIFIED, System.currentTimeMillis()); CmsRequestUtil.setNoCacheHeaders(res); } RfsCmsResource rfsFile = (RfsCmsResource) resource; File f = rfsFile.getRfsFile(); if (f.getName().toLowerCase().endsWith("webm")) { res.setHeader("Content-Type", "video/webm"); } else if (f.getName().toLowerCase().endsWith("ogv")) { res.setHeader("Content-Type", "video/ogg"); } else if (f.getName().toLowerCase().endsWith("mp4")) { res.setHeader("Content-Type", "video/mp4"); } if (req.getMethod().equalsIgnoreCase("HEAD")) { res.setStatus(HttpServletResponse.SC_OK); res.setHeader("Accept-Ranges", "bytes"); res.setContentLength((int) f.length()); return; } else if (req.getMethod().equalsIgnoreCase("GET")) { if (req.getHeader("Range") != null) { String range = req.getHeader("Range"); String[] string = range.split("=")[1].split("-"); long start = Long.parseLong(string[0]); long end = string.length == 1 ? f.length() - 1 : Long.parseLong(string[1]); long length = end - start + 1; res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); res.setHeader("Accept-Ranges", "bytes"); res.setHeader("Content-Length", "" + length); res.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + f.length()); RandomAccessFile ras = null; try { ras = new RandomAccessFile(f, "r"); ras.seek(start); final int chunkSize = 4096; byte[] buffy = new byte[chunkSize]; int nextChunkSize = length > chunkSize ? chunkSize : (int) length; long bytesLeft = length; while (bytesLeft > 0) { ras.read(buffy, 0, nextChunkSize); res.getOutputStream().write(buffy, 0, nextChunkSize); res.getOutputStream().flush(); bytesLeft = bytesLeft - nextChunkSize; nextChunkSize = bytesLeft > chunkSize ? chunkSize : (int) bytesLeft; /* * to simulate lower bandwidth */ /* try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } */ } } finally { if (ras != null) { ras.close(); } } return; } } res.setStatus(HttpServletResponse.SC_OK); res.setHeader("Accept-Ranges", "bytes"); res.setContentLength((int) f.length()); service(cms, resource, req, res); }
From source file:org.mycore.common.content.util.MCRServletContentHelper.java
/** * Serve the specified content, optionally including the data content. * This method handles both GET and HEAD requests. *//*w w w . jav a 2 s.c o m*/ public static void serveContent(final MCRContent content, final HttpServletRequest request, final HttpServletResponse response, final ServletContext context, final Config config, final boolean withContent) throws IOException { boolean serveContent = withContent; final String path = getRequestPath(request); if (LOGGER.isDebugEnabled()) { if (serveContent) { LOGGER.debug("Serving '" + path + "' headers and data"); } else { LOGGER.debug("Serving '" + path + "' headers only"); } } if (response.isCommitted()) { //getContent has access to response return; } final boolean isError = response.getStatus() >= HttpServletResponse.SC_BAD_REQUEST; if (content == null && !isError) { response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI()); return; } //Check if all conditional header validate if (!isError && !checkIfHeaders(request, response, content)) { return; } // Find content type. String contentType = content.getMimeType(); final String filename = getFileName(request, content); if (contentType == null) { contentType = context.getMimeType(filename); content.setMimeType(contentType); } String enc = content.getEncoding(); if (enc != null) { contentType = String.format(Locale.ROOT, "%s; charset=%s", contentType, enc); } String eTag = null; ArrayList<Range> ranges = null; if (!isError) { eTag = content.getETag(); if (config.useAcceptRanges) { response.setHeader("Accept-Ranges", "bytes"); } ranges = parseRange(request, response, content); response.setHeader("ETag", eTag); long lastModified = content.lastModified(); if (lastModified >= 0) { response.setDateHeader("Last-Modified", lastModified); } if (serveContent) { String dispositionType = request.getParameter("dl") == null ? "inline" : "attachment"; response.setHeader("Content-Disposition", dispositionType + ";filename=\"" + filename + "\""); } } final long contentLength = content.length(); //No Content to serve? if (contentLength == 0) { serveContent = false; } if (content.isUsingSession()) { response.addHeader("Cache-Control", "private, max-age=0, must-revalidate"); response.addHeader("Vary", "*"); } try (ServletOutputStream out = serveContent ? response.getOutputStream() : null) { if (serveContent) { try { response.setBufferSize(config.outputBufferSize); } catch (final IllegalStateException e) { //does not matter if we fail } } if (response instanceof ServletResponseWrapper) { if (request.getHeader("Range") != null) { LOGGER.warn("Response is wrapped by ServletResponseWrapper, no 'Range' requests supported."); } ranges = FULL; } if (isError || (ranges == null || ranges.isEmpty()) && request.getHeader("Range") == null || ranges == FULL) { //No ranges if (contentType != null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("contentType='" + contentType + "'"); } response.setContentType(contentType); } if (contentLength >= 0) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("contentLength=" + contentLength); } setContentLengthLong(response, contentLength); } if (serveContent) { copy(content, out, config.inputBufferSize, config.outputBufferSize); } } else { if (ranges == null || ranges.isEmpty()) { return; } // Partial content response. response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); if (ranges.size() == 1) { final Range range = ranges.get(0); response.addHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + range.length); final long length = range.end - range.start + 1; setContentLengthLong(response, length); if (contentType != null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("contentType='" + contentType + "'"); } response.setContentType(contentType); } if (serveContent) { copy(content, out, range, config.inputBufferSize, config.outputBufferSize); } } else { response.setContentType("multipart/byteranges; boundary=" + MIME_BOUNDARY); if (serveContent) { copy(content, out, ranges.iterator(), contentType, config.inputBufferSize, config.outputBufferSize); } } } } }