@Override public boolean put(String contentUrl, ContentReader source) { File cacheFile = createCacheFile(); // Copy the content from the source into a cache file if (source.getSize() > 0L) { source.getContent(cacheFile); // Add a record of the cached file to the in-memory cache. recordCacheEntries(contentUrl, cacheFile); return true; } return false; }
/** * Stream content implementation * * @param req The request * @param res The response * @param reader The reader * @param nodeRef The content nodeRef if applicable * @param propertyQName The content property if applicable * @param attach Indicates whether the content should be streamed as an attachment or not * @param modified Modified date of content * @param eTag ETag to use * @param attachFileName Optional file name to use when attach is <code>true</code> * @throws IOException */ public void streamContentImpl( WebScriptRequest req, WebScriptResponse res, ContentReader reader, final NodeRef nodeRef, final QName propertyQName, final boolean attach, final Date modified, String eTag, final String attachFileName, Map<String, Object> model) throws IOException { setAttachment(null, res, attach, attachFileName); // establish mimetype String mimetype = reader.getMimetype(); String extensionPath = req.getExtensionPath(); if (mimetype == null || mimetype.length() == 0) { mimetype = MimetypeMap.MIMETYPE_BINARY; int extIndex = extensionPath.lastIndexOf('.'); if (extIndex != -1) { String ext = extensionPath.substring(extIndex + 1); mimetype = mimetypeService.getMimetype(ext); } } res.setHeader(HEADER_ACCEPT_RANGES, "bytes"); try { boolean processedRange = false; String range = req.getHeader(HEADER_CONTENT_RANGE); final long size = reader.getSize(); final String encoding = reader.getEncoding(); if (attach) { final String finalMimetype = mimetype; eventPublisher.publishEvent( new EventPreparator() { @Override public Event prepareEvent(String user, String networkId, String transactionId) { String siteId = siteService.getSiteShortName(nodeRef); return new ContentEventImpl( ContentEvent.DOWNLOAD, user, networkId, transactionId, nodeRef.getId(), siteId, propertyQName.toString(), Client.webclient, attachFileName, finalMimetype, size, encoding); } }); } if (range == null) { range = req.getHeader(HEADER_RANGE); } if (range != null) { if (logger.isDebugEnabled()) logger.debug("Found content range header: " + range); // ensure the range header is starts with "bytes=" and process the range(s) if (range.length() > 6) { if (range.indexOf(',') != -1 && (nodeRef == null || propertyQName == null)) { if (logger.isInfoEnabled()) logger.info("Multi-range only supported for nodeRefs"); } else { HttpRangeProcessor rangeProcessor = new HttpRangeProcessor(contentService); processedRange = rangeProcessor.processRange( res, reader, range.substring(6), nodeRef, propertyQName, mimetype, req.getHeader(HEADER_USER_AGENT)); } } } if (processedRange == false) { if (logger.isDebugEnabled()) logger.debug("Sending complete file content..."); // set mimetype for the content and the character encoding for the stream res.setContentType(mimetype); res.setContentEncoding(encoding); // return the complete entity range res.setHeader( HEADER_CONTENT_RANGE, "bytes 0-" + Long.toString(size - 1L) + "/" + Long.toString(size)); res.setHeader(HEADER_CONTENT_LENGTH, Long.toString(size)); // set caching setResponseCache(res, modified, eTag, model); // get the content and stream directly to the response output stream // assuming the repository is capable of streaming in chunks, this should allow large files // to be streamed directly to the browser response stream. reader.getContent(res.getOutputStream()); } } catch (SocketException e1) { // the client cut the connection - our mission was accomplished apart from a little error // message if (logger.isInfoEnabled()) logger.info("Client aborted stream read:\n\tcontent: " + reader); } catch (ContentIOException e2) { if (logger.isInfoEnabled()) logger.info("Client aborted stream read:\n\tcontent: " + reader); } }