diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.desc.xml index b99309f950..de5c95bd5f 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.desc.xml @@ -1,8 +1,8 @@ Thumbnails Get a named thumbnail for a content resource - /api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname} - /api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname} + /api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?} + /api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?} argument guest required diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.js b/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.js index f9b92b3eab..d71ebc1416 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.js +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/thumbnail/thumbnail.get.js @@ -22,17 +22,60 @@ function main() return; } + // Get the queue create flag + var qc = false; + var qcString = args.qc; + if (qcString != null) + { + qc = utils.toBoolean(qcString); + } + + // Get the place holder flag + var ph = false; + var phString = args.ph; + if (phString != null) + { + ph = utils.toBoolean(phString); + } + // Get the thumbnail var thumbnail = node.getThumbnail(thumbnailName); if (thumbnail == null) { - // 404 since no thumbnail was found - status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found"); - return; + // Queue the creation of the thumbnail if appropriate + if (qc == true) + { + node.createThumbnail(thumbnailName, true); + } + + if (ph == true) + { + // Try and get the place holder resource + var phPath = thumbnailService.getPlaceHolderResourcePath(thumbnailName); + if (phPath == null) + { + // 404 since no thumbnail was found + status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found and no place holde resource set for '" + thumbnailName + "'"); + return; + } + else + { + // Set the resouce path in the model ready for the content stream to send back to the client + model.contentPath = phPath; + } + } + else + { + // 404 since no thumbnail was found + status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found"); + return; + } } - - // Place the details of the thumbnail into the model, this will be used to stream the content to the client - model.contentNode = thumbnail; + else + { + // Place the details of the thumbnail into the model, this will be used to stream the content to the client + model.contentNode = thumbnail; + } } main(); \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java index 509b7e56b3..cdfa87cd77 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java +++ b/source/java/org/alfresco/repo/web/scripts/content/StreamContent.java @@ -24,7 +24,10 @@ */ package org.alfresco.repo.web.scripts.content; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.Writer; import java.net.SocketException; import java.util.Date; @@ -36,6 +39,7 @@ import javax.servlet.http.HttpServletResponse; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.filestore.FileContentReader; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; @@ -45,6 +49,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.TempFileProvider; import org.alfresco.web.scripts.AbstractWebScript; import org.alfresco.web.scripts.Cache; import org.alfresco.web.scripts.Container; @@ -59,6 +64,9 @@ import org.alfresco.web.scripts.servlet.WebScriptServletRequest; import org.alfresco.web.scripts.servlet.WebScriptServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.util.FileCopyUtils; + +import de.schlichtherle.io.FileOutputStream; /** * Web script 'type' that can be used when the binary data of a content property needs to be streamed back to the client @@ -169,33 +177,44 @@ public class StreamContent extends AbstractWebScript sendStatus(req, res, status, cache, format, templateModel); } else - { - // Get the content parameters from the model - NodeRef nodeRef = (NodeRef)model.get("contentNode"); - if (nodeRef == null) - { - throw new WebScriptException("The content node was not specified so the content cannot be streamed to the client"); - } - QName propertyQName = null; - String contentProperty = (String)model.get("contentProperty"); - if (contentProperty == null) - { - // default to the standard content property - propertyQName = ContentModel.PROP_CONTENT; - } - else - { - propertyQName = QName.createQName(contentProperty); - } + { + // Get the attachement property value Boolean attachBoolean = (Boolean)model.get("attach"); boolean attach = false; if (attachBoolean != null) { attach = attachBoolean.booleanValue(); } - - // Stream the content - streamContent(req, res, nodeRef, propertyQName, attach); + + String contentPath = (String)model.get("contentPath"); + if (contentPath == null) + { + // Get the content parameters from the model + NodeRef nodeRef = (NodeRef)model.get("contentNode"); + if (nodeRef == null) + { + throw new WebScriptException("The content node was not specified so the content cannot be streamed to the client"); + } + QName propertyQName = null; + String contentProperty = (String)model.get("contentProperty"); + if (contentProperty == null) + { + // default to the standard content property + propertyQName = ContentModel.PROP_CONTENT; + } + else + { + propertyQName = QName.createQName(contentProperty); + } + + // Stream the content + streamContent(req, res, nodeRef, propertyQName, attach); + } + else + { + // Stream the content + streamContent(req, res, contentPath, attach); + } } } catch(Throwable e) @@ -345,6 +364,72 @@ public class StreamContent extends AbstractWebScript } } + // get the content reader + ContentReader reader = contentService.getReader(nodeRef, propertyQName); + if (reader == null || !reader.exists()) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to locate content for node ref " + nodeRef + " (property: " + propertyQName.toString() + ")"); + } + + // Stream the cotent + streamContentImpl(req, res, reader, attach, modified); + } + + /** + * Streams content back to client from a given resource path + * + * @param req + * @param res + * @param resourcePath + * @param attach + * @throws IOException + */ + protected void streamContent(WebScriptRequest req, WebScriptResponse res, String resourcePath, boolean attach) + throws IOException + { + String ext = ""; + String mimetype = MimetypeMap.MIMETYPE_BINARY; + int extIndex = resourcePath.lastIndexOf('.'); + if (extIndex != -1) + { + ext = resourcePath.substring(extIndex + 1); + String mt = mimetypeService.getMimetypesByExtension().get(ext); + if (mt != null) + { + mimetype = mt; + } + } + + File file = TempFileProvider.createTempFile("streamContent-", ext); + InputStream is = this.getClass().getClassLoader().getResourceAsStream(resourcePath); + OutputStream os = new FileOutputStream(file); + FileCopyUtils.copy(is, os); + + FileContentReader reader = new FileContentReader(file); + reader.setMimetype(mimetype); + reader.setEncoding("UTF-8"); + + streamContentImpl(req, res, reader, attach, new Date(file.lastModified())); + + } + + /** + * Stream content implementation + * + * @param req + * @param res + * @param reader + * @param attach + * @param modified + * @throws IOException + */ + protected void streamContentImpl(WebScriptRequest req, WebScriptResponse res, ContentReader reader, boolean attach, Date modified) + throws IOException + { + + HttpServletRequest httpReq = ((WebScriptServletRequest)req).getHttpServletRequest(); + HttpServletResponse httpRes = ((WebScriptServletResponse)res).getHttpServletResponse(); + // handle attachment if (attach == true) { @@ -353,13 +438,6 @@ public class StreamContent extends AbstractWebScript httpRes.setHeader("Content-Disposition", "attachment"); } - // get the content reader - ContentReader reader = contentService.getReader(nodeRef, propertyQName); - if (reader == null || !reader.exists()) - { - throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to locate content for node ref " + nodeRef + " (property: " + propertyQName.toString() + ")"); - } - // establish mimetype String mimetype = reader.getMimetype(); String extensionPath = req.getExtensionPath(); @@ -401,13 +479,12 @@ public class StreamContent extends AbstractWebScript { // 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\tnode: " + nodeRef + "\n\tcontent: " + reader); + logger.info("Client aborted stream read:\n\tcontent: " + reader); } catch (ContentIOException e2) { if (logger.isInfoEnabled()) - logger.info("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader); + logger.info("Client aborted stream read:\n\tcontent: " + reader); } } - } diff --git a/source/java/org/alfresco/repo/web/scripts/thumbnail/ThumbnailServiceTest.java b/source/java/org/alfresco/repo/web/scripts/thumbnail/ThumbnailServiceTest.java index 49a6ee744b..8a3a919e2d 100644 --- a/source/java/org/alfresco/repo/web/scripts/thumbnail/ThumbnailServiceTest.java +++ b/source/java/org/alfresco/repo/web/scripts/thumbnail/ThumbnailServiceTest.java @@ -131,7 +131,7 @@ public class ThumbnailServiceTest extends BaseWebScriptTest public void testCreateAsyncThumbnail() throws Exception { - // Check for pdfToSWF transformation before doing test + // Check for pdfToSWF transformation before doing test if (this.contentService.getTransformer(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_FLASH) != null) { String url = "/api/node/" + pdfNode.getStoreRef().getProtocol() + "/" + pdfNode.getStoreRef().getIdentifier() + "/" + pdfNode.getId() + "/content/thumbnails?as=true"; @@ -179,5 +179,27 @@ public class ThumbnailServiceTest extends BaseWebScriptTest } } + public void testPlaceHolder() + throws Exception + { + if (this.contentService.getTransformer(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_FLASH) != null) + { + // Check that there is no place holder set for webpreview + this.getRequest(getThumbnailsURL(pdfNode) + "/webpreview", 404); + this.getRequest(getThumbnailsURL(pdfNode) + "/webpreview?ph=true", 404); + } + + // Check that here is a place holder for medium + this.getRequest(getThumbnailsURL(jpgNode) + "/medium", 404); + this.getRequest(getThumbnailsURL(jpgNode) + "/medium?ph=true", 200); + + System.out.println(getThumbnailsURL(jpgNode) + "/medium?ph=true"); + } + + private String getThumbnailsURL(NodeRef nodeRef) + { + return "/api/node/" + nodeRef.getStoreRef().getProtocol() + "/" + nodeRef.getStoreRef().getIdentifier() + "/" + nodeRef.getId() + "/content/thumbnails"; + } + }