diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index 7f5187378f..c18a6f948b 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -1061,6 +1061,7 @@
+
diff --git a/source/java/org/alfresco/rest/api/Renditions.java b/source/java/org/alfresco/rest/api/Renditions.java
index 4bbeb8d612..c331dbf4af 100644
--- a/source/java/org/alfresco/rest/api/Renditions.java
+++ b/source/java/org/alfresco/rest/api/Renditions.java
@@ -20,6 +20,7 @@
package org.alfresco.rest.api;
import org.alfresco.rest.api.model.Rendition;
+import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
@@ -58,4 +59,14 @@ public interface Renditions
* @param parameters the {@link Parameters} object to get the parameters passed into the request
*/
void createRendition(String nodeId, Rendition rendition, Parameters parameters);
+
+ /**
+ * Downloads rendition.
+ *
+ * @param nodeId the source node id
+ * @param renditionId the rendition id
+ * @param parameters the {@link Parameters} object to get the parameters passed into the request
+ * @return the rendition stream
+ */
+ BinaryResource getContent(String nodeId, String renditionId, Parameters parameters);
}
diff --git a/source/java/org/alfresco/rest/api/impl/RenditionsImpl.java b/source/java/org/alfresco/rest/api/impl/RenditionsImpl.java
index 8510f80b6f..651e4bf84c 100644
--- a/source/java/org/alfresco/rest/api/impl/RenditionsImpl.java
+++ b/source/java/org/alfresco/rest/api/impl/RenditionsImpl.java
@@ -24,15 +24,22 @@ import org.alfresco.query.PagingResults;
import org.alfresco.repo.thumbnail.ThumbnailDefinition;
import org.alfresco.repo.thumbnail.ThumbnailHelper;
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
+import org.alfresco.repo.thumbnail.script.ScriptThumbnailService;
import org.alfresco.rest.antlr.WhereClauseParser;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.Renditions;
import org.alfresco.rest.api.model.ContentInfo;
import org.alfresco.rest.api.model.Rendition;
import org.alfresco.rest.api.model.Rendition.RenditionStatus;
+import org.alfresco.rest.framework.core.exceptions.ApiException;
import org.alfresco.rest.framework.core.exceptions.DisabledServiceException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
+import org.alfresco.rest.framework.core.exceptions.NotFoundException;
+import org.alfresco.rest.framework.resource.content.BinaryResource;
+import org.alfresco.rest.framework.resource.content.ContentInfoImpl;
+import org.alfresco.rest.framework.resource.content.FileBinaryResource;
+import org.alfresco.rest.framework.resource.content.NodeBinaryResource;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.rest.framework.resource.parameters.Parameters;
@@ -52,8 +59,16 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyCheck;
+import org.alfresco.util.TempFileProvider;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.ResourceLoader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -63,19 +78,23 @@ import java.util.TreeMap;
/**
* @author Jamal Kaabi-Mofrad
*/
-public class RenditionsImpl implements Renditions
+public class RenditionsImpl implements Renditions, ResourceLoaderAware
{
+ private static final Log LOGGER = LogFactory.getLog(RenditionsImpl.class);
+
private static final String PARAM_status = "status";
private static final Set RENDITION_STATUS_COLLECTION_EQUALS_QUERY_PROPERTIES = Collections.singleton(PARAM_status);
private Nodes nodes;
private NodeService nodeService;
private ThumbnailService thumbnailService;
+ private ScriptThumbnailService scriptThumbnailService;
private RenditionService renditionService;
private MimetypeService mimetypeService;
private ActionService actionService;
private NamespaceService namespaceService;
private ServiceRegistry serviceRegistry;
+ private ResourceLoader resourceLoader;
public void setNodes(Nodes nodes)
{
@@ -87,15 +106,27 @@ public class RenditionsImpl implements Renditions
this.thumbnailService = thumbnailService;
}
+ public void setScriptThumbnailService(ScriptThumbnailService scriptThumbnailService)
+ {
+ this.scriptThumbnailService = scriptThumbnailService;
+ }
+
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader)
+ {
+ this.resourceLoader = resourceLoader;
+ }
+
public void init()
{
PropertyCheck.mandatory(this, "nodes", nodes);
PropertyCheck.mandatory(this, "thumbnailService", thumbnailService);
+ PropertyCheck.mandatory(this, "scriptThumbnailService", scriptThumbnailService);
PropertyCheck.mandatory(this, "serviceRegistry", serviceRegistry);
this.nodeService = serviceRegistry.getNodeService();
@@ -238,6 +269,86 @@ public class RenditionsImpl implements Renditions
actionService.executeAction(action, sourceNodeRef, true, true);
}
+ @Override
+ public BinaryResource getContent(String nodeId, String renditionId, Parameters parameters)
+ {
+ final NodeRef sourceNodeRef = validateSourceNode(nodeId);
+ final NodeRef renditionNodeRef = getRenditionByName(sourceNodeRef, renditionId, parameters);
+
+ // By default set attachment header (with rendition Id) unless attachment=false
+ boolean attach = true;
+ String attachment = parameters.getParameter("attachment");
+ if (attachment != null)
+ {
+ attach = Boolean.valueOf(attachment);
+ }
+ final String attachFileName = (attach ? renditionId : null);
+
+ if (renditionNodeRef == null)
+ {
+ boolean isPlaceholder = Boolean.valueOf(parameters.getParameter("placeholder"));
+ if (!isPlaceholder)
+ {
+ throw new NotFoundException("Thumbnail was not found for [" + renditionId + ']');
+ }
+ ContentData contentData = (ContentData) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CONTENT);
+ String sourceNodeMimeType = null;
+ if (contentData != null)
+ {
+ sourceNodeMimeType = contentData.getMimetype();
+ }
+ // resource based on the content's mimeType and rendition id
+ String phPath = scriptThumbnailService.getMimeAwarePlaceHolderResourcePath(renditionId, sourceNodeMimeType);
+ if (phPath == null)
+ {
+ // 404 since no thumbnail was found
+ throw new NotFoundException("Thumbnail was not found and no placeholder resource available for [" + renditionId + ']');
+ }
+ else
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Retrieving content from resource path [" + phPath + ']');
+ }
+ // get extension of resource
+ String ext = "";
+ int extIndex = phPath.lastIndexOf('.');
+ if (extIndex != -1)
+ {
+ ext = phPath.substring(extIndex);
+ }
+
+ try
+ {
+ final String resourcePath = "classpath:" + phPath;
+ InputStream inputStream = resourceLoader.getResource(resourcePath).getInputStream();
+ // create temporary file
+ File file = TempFileProvider.createTempFile(inputStream, "RenditionsApi-", ext);
+ return new FileBinaryResource(file, attachFileName);
+ }
+ catch (Exception ex)
+ {
+ if (LOGGER.isErrorEnabled())
+ {
+ LOGGER.error("Couldn't load the placeholder." + ex.getMessage());
+ }
+ new ApiException("Couldn't load the placeholder.");
+ }
+ }
+ }
+
+ Map nodeProps = nodeService.getProperties(renditionNodeRef);
+ ContentData contentData = (ContentData) nodeProps.get(ContentModel.PROP_CONTENT);
+
+ org.alfresco.rest.framework.resource.content.ContentInfo contentInfo = null;
+ if (contentData != null)
+ {
+ contentInfo = new ContentInfoImpl(contentData.getMimetype(), contentData.getEncoding(), contentData.getSize(), contentData.getLocale());
+ }
+
+ return new NodeBinaryResource(renditionNodeRef, ContentModel.PROP_CONTENT, contentInfo, attachFileName);
+ }
+
protected NodeRef getRenditionByName(NodeRef nodeRef, String renditionId, Parameters parameters)
{
if (StringUtils.isEmpty(renditionId))
diff --git a/source/java/org/alfresco/rest/api/nodes/NodeRenditionsRelation.java b/source/java/org/alfresco/rest/api/nodes/NodeRenditionsRelation.java
index f74c6cdc87..d8969ae838 100644
--- a/source/java/org/alfresco/rest/api/nodes/NodeRenditionsRelation.java
+++ b/source/java/org/alfresco/rest/api/nodes/NodeRenditionsRelation.java
@@ -21,9 +21,12 @@ package org.alfresco.rest.api.nodes;
import org.alfresco.rest.api.Renditions;
import org.alfresco.rest.api.model.Rendition;
+import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
+import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction;
+import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
@@ -42,6 +45,7 @@ import java.util.List;
public class NodeRenditionsRelation implements RelationshipResourceAction.Read,
RelationshipResourceAction.ReadById,
RelationshipResourceAction.Create,
+ RelationshipResourceBinaryAction.Read,
InitializingBean
{
@@ -80,4 +84,12 @@ public class NodeRenditionsRelation implements RelationshipResourceAction.Read.
+ */
+
+package org.alfresco.rest.framework.resource.content;
+
+/**
+ * An abstract binary resource.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+public class AbstractBinaryResource implements BinaryResource
+{
+ final String attachFileName;
+
+ public AbstractBinaryResource(String attachFileName)
+ {
+ this.attachFileName = attachFileName;
+ }
+
+ public String getAttachFileName()
+ {
+ return attachFileName;
+ }
+}
diff --git a/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java b/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java
index ed41842a88..903fd7ec5c 100755
--- a/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java
+++ b/source/java/org/alfresco/rest/framework/resource/content/FileBinaryResource.java
@@ -30,16 +30,21 @@ import java.io.File;
/**
* A binary resource based on a File.
- *
+ *
* @author Gethin James
*/
-public class FileBinaryResource implements BinaryResource
+public class FileBinaryResource extends AbstractBinaryResource
{
final File file;
public FileBinaryResource(File file)
{
- super();
+ this(file, null);
+ }
+
+ public FileBinaryResource(File file, String attachFileName)
+ {
+ super(attachFileName);
this.file = file;
}
diff --git a/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java b/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java
index 6410d84e4b..21e176d73b 100755
--- a/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java
+++ b/source/java/org/alfresco/rest/framework/resource/content/NodeBinaryResource.java
@@ -30,25 +30,22 @@ import org.alfresco.service.namespace.QName;
/**
* A binary resource based on a Node reference.
- *
+ *
* @author Gethin James
*/
-public class NodeBinaryResource implements BinaryResource
+public class NodeBinaryResource extends AbstractBinaryResource
{
final NodeRef nodeRef;
final QName propertyQName;
final ContentInfo contentInfo;
- final String attachFileName;
-
+
public NodeBinaryResource(NodeRef nodeRef, QName propertyQName, ContentInfo contentInfo, String attachFileName)
{
- super();
-
+ super(attachFileName);
this.nodeRef = nodeRef;
this.propertyQName = propertyQName;
this.contentInfo = contentInfo;
- this.attachFileName = attachFileName;
}
public NodeRef getNodeRef()
@@ -65,9 +62,4 @@ public class NodeBinaryResource implements BinaryResource
{
return this.contentInfo;
}
-
- public String getAttachFileName()
- {
- return this.attachFileName;
- }
-}
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java b/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java
index 5b61920df6..802bcc4014 100644
--- a/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java
+++ b/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java
@@ -47,6 +47,7 @@ import org.alfresco.rest.framework.resource.content.ContentInfo;
import org.alfresco.rest.framework.resource.content.FileBinaryResource;
import org.alfresco.rest.framework.resource.content.NodeBinaryResource;
import org.alfresco.rest.framework.resource.parameters.Params;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonGenerationException;
@@ -90,11 +91,11 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
@Override
public void execute(final Api api, final WebScriptRequest req, final WebScriptResponse res) throws IOException
{
- try
- {
+ try
+ {
final Map respons = new HashMap();
final Map templateVars = req.getServiceMatch().getTemplateVars();
- final ResourceWithMetadata resource = locator.locateResource(api,templateVars, httpMethod);
+ final ResourceWithMetadata resource = locator.locateResource(api,templateVars, httpMethod);
final Params params = paramsExtractor.extractParams(resource.getMetaData(),req);
final boolean isReadOnly = HttpMethod.GET==httpMethod;
@@ -132,19 +133,19 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
}
}
- }
- catch (ApiException apiException)
- {
- renderErrorResponse(resolveException(apiException), res);
- }
- catch (WebScriptException webException)
- {
- renderErrorResponse(resolveException(webException), res);
- }
- catch (RuntimeException runtimeException)
- {
- renderErrorResponse(resolveException(runtimeException), res);
- }
+ }
+ catch (ApiException apiException)
+ {
+ renderErrorResponse(resolveException(apiException), res);
+ }
+ catch (WebScriptException webException)
+ {
+ renderErrorResponse(resolveException(webException), res);
+ }
+ catch (RuntimeException runtimeException)
+ {
+ renderErrorResponse(resolveException(runtimeException), res);
+ }
}
public Object execute(final ResourceWithMetadata resource, final Params params, final WebScriptResponse res, boolean isReadOnly)
@@ -176,6 +177,8 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
if (resource instanceof FileBinaryResource)
{
FileBinaryResource fileResource = (FileBinaryResource) resource;
+ // if requested, set attachment
+ setAttachment(res, fileResource.getAttachFileName());
streamer.streamContent(req, res, fileResource.getFile(), null, false, null, null);
}
else if (resource instanceof NodeBinaryResource)
@@ -183,16 +186,21 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements
NodeBinaryResource nodeResource = (NodeBinaryResource) resource;
ContentInfo contentInfo = nodeResource.getContentInfo();
setContentInfoOnResponse(res,contentInfo);
- String attachFileName = nodeResource.getAttachFileName();
- if ((attachFileName != null) && (attachFileName.length() > 0))
- {
- String headerValue = "attachment; filename=\"" + attachFileName + "\"; filename*=UTF-8''" + URLEncoder.encode(attachFileName);
- res.setHeader(HDR_NAME_CONTENT_DISPOSITION, headerValue);
- }
+ // if requested, set attachment
+ setAttachment(res, nodeResource.getAttachFileName());
streamer.streamContent(req, res, nodeResource.getNodeRef(), nodeResource.getPropertyQName(), false, null, null);
}
}
+ private void setAttachment(final WebScriptResponse res, final String attachFileName)
+ {
+ if (StringUtils.isNotEmpty(attachFileName))
+ {
+ String headerValue = "attachment; filename=\"" + attachFileName + "\"; filename*=UTF-8''" + URLEncoder.encode(attachFileName);
+ res.setHeader(HDR_NAME_CONTENT_DISPOSITION, headerValue);
+ }
+ }
+
/**
* The response status must be set before the response is written by Jackson (which will by default close and commit the response).
* In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important.
diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
index 76d952ccf9..a8e0a911f0 100644
--- a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
@@ -147,10 +147,15 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
}
protected HttpResponse getSingle(String url, String runAsUser, String entityId, int expectedStatus) throws Exception
+ {
+ return getSingle(url, runAsUser, entityId, null, expectedStatus);
+ }
+
+ protected HttpResponse getSingle(String url, String runAsUser, String entityId, Map params, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
- HttpResponse response = publicApiClient.get(getScope(), url, entityId, null, null, null);
+ HttpResponse response = publicApiClient.get(getScope(), url, entityId, null, null, params);
checkStatus(expectedStatus, response.getStatusCode());
return response;
diff --git a/source/test-java/org/alfresco/rest/api/tests/RenditionsTest.java b/source/test-java/org/alfresco/rest/api/tests/RenditionsTest.java
index 2d1185fe5d..4886a6b9a9 100644
--- a/source/test-java/org/alfresco/rest/api/tests/RenditionsTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/RenditionsTest.java
@@ -53,6 +53,8 @@ import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.InputStream;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -370,6 +372,141 @@ public class RenditionsTest extends AbstractBaseApiTest
}
}
+ /**
+ * Tests download rendition.
+ * GET:
+ * {@literal :/alfresco/api//public/alfresco/versions/1/nodes//renditions//content}
+ */
+ @Test
+ public void testDownloadRendition() throws Exception
+ {
+ // Create a folder within the site document's library
+ String folderName = "folder" + System.currentTimeMillis();
+ String folder_Id = addToDocumentLibrary(userOneN1Site, folderName, ContentModel.TYPE_FOLDER, userOneN1.getId());
+
+ // Create multipart request
+ String fileName = "quick.pdf";
+ File file = getResourceFile(fileName);
+ MultiPartBuilder multiPartBuilder = MultiPartBuilder.create()
+ .setFileData(new FileData(fileName, file, MimetypeMap.MIMETYPE_PDF));
+ MultiPartRequest reqBody = multiPartBuilder.build();
+
+ // Upload quick.pdf file into 'folder'
+ HttpResponse response = post("nodes/" + folder_Id + "/children", userOneN1.getId(), reqBody.getBody(), null, reqBody.getContentType(), 201);
+ Document document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+ String contentNodeId = document.getId();
+
+ // Get rendition (not created yet) information for node
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib", 200);
+ Rendition rendition = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Rendition.class);
+ assertNotNull(rendition);
+ assertEquals(RenditionStatus.NOT_CREATED, rendition.getStatus());
+
+ // Download placeholder - by default with Content-Disposition header
+ Map params = new HashMap<>();
+ params.put("placeholder", "true");
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), ("doclib/content"), params, 200);
+ assertNotNull(response.getResponseAsBytes());
+ Map responseHeaders = response.getHeaders();
+ assertNotNull(responseHeaders);
+ String contentDisposition = responseHeaders.get("Content-Disposition");
+ assertNotNull(contentDisposition);
+ assertTrue(contentDisposition.contains("filename=\"doclib\""));
+ String contentType = responseHeaders.get("Content-Type");
+ assertNotNull(contentType);
+ assertTrue(contentType.startsWith(MimetypeMap.MIMETYPE_IMAGE_PNG));
+
+ // Download placeholder - without Content-Disposition header (attachment=false)
+ params.put("attachment", "false");
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), ("doclib/content"), params, 200);
+ assertNotNull(response.getResponseAsBytes());
+ responseHeaders = response.getHeaders();
+ assertNotNull(responseHeaders);
+ assertNull(responseHeaders.get("Content-Disposition"));
+ contentType = responseHeaders.get("Content-Type");
+ assertNotNull(contentType);
+ assertTrue(contentType.startsWith(MimetypeMap.MIMETYPE_IMAGE_PNG));
+
+ // Create and get 'doclib' rendition
+ rendition = createAndGetRendition(contentNodeId, "doclib");
+ assertNotNull(rendition);
+ assertEquals(RenditionStatus.CREATED, rendition.getStatus());
+
+ // Download rendition - by default with Content-Disposition header
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib/content", 200);
+ assertNotNull(response.getResponseAsBytes());
+ responseHeaders = response.getHeaders();
+ assertNotNull(responseHeaders);
+ contentDisposition = responseHeaders.get("Content-Disposition");
+ assertNotNull(contentDisposition);
+ assertTrue(contentDisposition.contains("filename=\"doclib\""));
+ contentType = responseHeaders.get("Content-Type");
+ assertNotNull(contentType);
+ assertTrue(contentType.startsWith(MimetypeMap.MIMETYPE_IMAGE_PNG));
+
+ // Download rendition - without Content-Disposition header (attachment=false)
+ params = Collections.singletonMap("attachment", "false");
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib/content", params, 200);
+ assertNotNull(response.getResponseAsBytes());
+ responseHeaders = response.getHeaders();
+ assertNotNull(responseHeaders);
+ assertNull(responseHeaders.get("Content-Disposition"));
+ contentType = responseHeaders.get("Content-Type");
+ assertNotNull(contentType);
+ assertTrue(contentType.startsWith(MimetypeMap.MIMETYPE_IMAGE_PNG));
+
+ // Download rendition - with Content-Disposition header (attachment=true) same as default
+ params = Collections.singletonMap("attachment", "true");
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib/content", params, 200);
+ assertNotNull(response.getResponseAsBytes());
+ responseHeaders = response.getHeaders();
+ assertNotNull(responseHeaders);
+ contentDisposition = responseHeaders.get("Content-Disposition");
+ assertNotNull(contentDisposition);
+ assertTrue(contentDisposition.contains("filename=\"doclib\""));
+ contentType = responseHeaders.get("Content-Type");
+ assertNotNull(contentType);
+ assertTrue(contentType.startsWith(MimetypeMap.MIMETYPE_IMAGE_PNG));
+
+ //-ve tests
+ // nodeId in the path parameter does not represent a file
+ getSingle(getRenditionsUrl(folder_Id), userOneN1.getId(), "doclib/content", 400);
+
+ // nodeId in the path parameter does not exist
+ getSingle(getRenditionsUrl(UUID.randomUUID().toString()), userOneN1.getId(), "doclib/content", 404);
+
+ // renditionId in the path parameter is not registered/available
+ getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), ("renditionId" + System.currentTimeMillis() + "/content"), 404);
+
+ InputStream inputStream = new ByteArrayInputStream("The quick brown fox jumps over the lazy dog".getBytes());
+ file = TempFileProvider.createTempFile(inputStream, "RenditionsTest-", ".abcdef");
+ reqBody = MultiPartBuilder.create()
+ .setFileData(new FileData(file.getName(), file, "application/unknown"))
+ .build();
+ // Upload temp file into 'folder'
+ response = post("nodes/" + folder_Id + "/children", userOneN1.getId(), reqBody.getBody(), null, reqBody.getContentType(), 201);
+ document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
+ contentNodeId = document.getId();
+ // Check there is no rendition created yet
+ response = getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib", 200);
+ rendition = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Rendition.class);
+ assertNotNull(rendition);
+ assertEquals(RenditionStatus.NOT_CREATED, rendition.getStatus());
+
+ // The content of the rendition does not exist and the placeholder parameter is not present
+ getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib/content", 404);
+
+ // The content of the rendition does not exist and the placeholder parameter has a value of "false"
+ params = Collections.singletonMap("placeholder", "false");
+ getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), "doclib/content", params, 404);
+
+ // The rendition does not exist, a placeholder is not available and the placeholder parameter has a value of "true"
+ params = Collections.singletonMap("placeholder", "true");
+ getSingle(getRenditionsUrl(contentNodeId), userOneN1.getId(), ("renditionId" + System.currentTimeMillis() + "/content"), params, 404);
+
+ //TODO add tests for 304 response
+ }
+
private String addToDocumentLibrary(final TestSite testSite, final String name, final QName type, String user)
{
return TenantUtil.runAsUserTenant(new TenantUtil.TenantRunAsWork()