mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Thumbanil API: suport for placeholder thumbnails added and queueing of thumbnails for creation on get
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9434 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
<webscript kind="org.alfresco.repository.content.stream">
|
<webscript kind="org.alfresco.repository.content.stream">
|
||||||
<shortname>Thumbnails</shortname>
|
<shortname>Thumbnails</shortname>
|
||||||
<description>Get a named thumbnail for a content resource</description>
|
<description>Get a named thumbnail for a content resource</description>
|
||||||
<url>/api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}</url>
|
<url>/api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?}</url>
|
||||||
<url>/api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}</url>
|
<url>/api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?}</url>
|
||||||
<format default="">argument</format>
|
<format default="">argument</format>
|
||||||
<authentication>guest</authentication>
|
<authentication>guest</authentication>
|
||||||
<transaction>required</transaction>
|
<transaction>required</transaction>
|
||||||
|
@@ -22,17 +22,60 @@ function main()
|
|||||||
return;
|
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
|
// Get the thumbnail
|
||||||
var thumbnail = node.getThumbnail(thumbnailName);
|
var thumbnail = node.getThumbnail(thumbnailName);
|
||||||
if (thumbnail == null)
|
if (thumbnail == null)
|
||||||
|
{
|
||||||
|
// 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
|
// 404 since no thumbnail was found
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found");
|
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Place the details of the thumbnail into the model, this will be used to stream the content to the client
|
// Place the details of the thumbnail into the model, this will be used to stream the content to the client
|
||||||
model.contentNode = thumbnail;
|
model.contentNode = thumbnail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main();
|
main();
|
@@ -24,7 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.web.scripts.content;
|
package org.alfresco.repo.web.scripts.content;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -36,6 +39,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
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.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
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.AccessStatus;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.TempFileProvider;
|
||||||
import org.alfresco.web.scripts.AbstractWebScript;
|
import org.alfresco.web.scripts.AbstractWebScript;
|
||||||
import org.alfresco.web.scripts.Cache;
|
import org.alfresco.web.scripts.Cache;
|
||||||
import org.alfresco.web.scripts.Container;
|
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.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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
|
* Web script 'type' that can be used when the binary data of a content property needs to be streamed back to the client
|
||||||
@@ -169,6 +177,17 @@ public class StreamContent extends AbstractWebScript
|
|||||||
sendStatus(req, res, status, cache, format, templateModel);
|
sendStatus(req, res, status, cache, format, templateModel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// Get the attachement property value
|
||||||
|
Boolean attachBoolean = (Boolean)model.get("attach");
|
||||||
|
boolean attach = false;
|
||||||
|
if (attachBoolean != null)
|
||||||
|
{
|
||||||
|
attach = attachBoolean.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
String contentPath = (String)model.get("contentPath");
|
||||||
|
if (contentPath == null)
|
||||||
{
|
{
|
||||||
// Get the content parameters from the model
|
// Get the content parameters from the model
|
||||||
NodeRef nodeRef = (NodeRef)model.get("contentNode");
|
NodeRef nodeRef = (NodeRef)model.get("contentNode");
|
||||||
@@ -187,16 +206,16 @@ public class StreamContent extends AbstractWebScript
|
|||||||
{
|
{
|
||||||
propertyQName = QName.createQName(contentProperty);
|
propertyQName = QName.createQName(contentProperty);
|
||||||
}
|
}
|
||||||
Boolean attachBoolean = (Boolean)model.get("attach");
|
|
||||||
boolean attach = false;
|
|
||||||
if (attachBoolean != null)
|
|
||||||
{
|
|
||||||
attach = attachBoolean.booleanValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stream the content
|
// Stream the content
|
||||||
streamContent(req, res, nodeRef, propertyQName, attach);
|
streamContent(req, res, nodeRef, propertyQName, attach);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stream the content
|
||||||
|
streamContent(req, res, contentPath, attach);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Throwable e)
|
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
|
// handle attachment
|
||||||
if (attach == true)
|
if (attach == true)
|
||||||
{
|
{
|
||||||
@@ -353,13 +438,6 @@ public class StreamContent extends AbstractWebScript
|
|||||||
httpRes.setHeader("Content-Disposition", "attachment");
|
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
|
// establish mimetype
|
||||||
String mimetype = reader.getMimetype();
|
String mimetype = reader.getMimetype();
|
||||||
String extensionPath = req.getExtensionPath();
|
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
|
// the client cut the connection - our mission was accomplished apart from a little error message
|
||||||
if (logger.isInfoEnabled())
|
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)
|
catch (ContentIOException e2)
|
||||||
{
|
{
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
logger.info("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
|
logger.info("Client aborted stream read:\n\tcontent: " + reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user