Monday, July 23, 2018

AEM 61 Extract Illustrator Artboards as PDF Assets in DAM Update Asset Workflow

AEM 61 Extract Illustrator Artboards as PDF Assets in DAM Update Asset Workflow


Goal


Add a workflow step in DAM Update Asset workflow to extract the Artboards of an Illustrator file and save them as PDFs. For ootb extraction and page viewer check documentation

Demo | Package Install | Source code

Thanks to my fantastic Adobe colleagues for code snippets


Artboards in Illustrator 



Artboards extracted as AEM PDF Assets



Solution


1) Create a workflow Process Step apps.experienceaem.pdf.CreatePDFRendition and add the code below

package apps.experienceaem.pdf;

import com.adobe.internal.io.ByteReader;
import com.adobe.internal.io.ByteWriter;
import com.adobe.internal.io.InputStreamByteReader;
import com.adobe.internal.io.RandomAccessFileByteWriter;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFException;
import com.adobe.internal.pdftoolkit.pdf.document.PDFDocument;
import com.adobe.internal.pdftoolkit.pdf.document.PDFOpenOptions;
import com.adobe.internal.pdftoolkit.pdf.document.PDFSaveFullOptions;
import com.adobe.internal.pdftoolkit.pdf.page.PDFPage;
import com.adobe.internal.pdftoolkit.pdf.page.PDFPageTree;
import com.adobe.internal.pdftoolkit.services.manipulations.PMMOptions;
import com.adobe.internal.pdftoolkit.services.manipulations.PMMService;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.AssetManager;
import com.day.cq.dam.commons.util.DamUtil;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.felix.scr.annotations.*;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Session;
import java.io.*;

@Component
@Service
@Properties({@Property(name = "process.label", value = "Experience AEM - Generate PDF Assets Process")})
public class CreatePDFRendition implements WorkflowProcess {
private static final Logger log = LoggerFactory.getLogger(CreatePDFRendition.class);

@Reference(policy = ReferencePolicy.STATIC)
private JcrResourceResolverFactory jcrResolverFactory;

public void execute(WorkItem workItem, WorkflowSession workflowSession,
MetaDataMap metaDataMap) throws WorkflowException {
long startTime = System.currentTimeMillis();

Asset asset = getAssetFromPayload(workItem, workflowSession.getSession());

try{
if(asset != null && asset.getName().endsWith(".ai")){
addPDFRendition(asset);
}
}catch(Exception e){
log.warn("Error generating pdf", e);
}

long endTime = System.currentTimeMillis();

log.info("CreatePDFRendition took {} seconds" , (endTime - startTime) / 1000);
}

private void addPDFRendition(Asset asset) throws Exception{
File tmpFile = null;
ByteWriter tmpFileWriter = null;

FileInputStream tmpFileReader = null;
InputStream assetOrigIS = null;

PDFDocument pdfDocument = null;
PDFDocument vectorFile = null;
PDFPage pdfPage = null;

try {
assetOrigIS = asset.getOriginal().getStream();

vectorFile = parseDocument(assetOrigIS);

PMMService pmmService = new PMMService(vectorFile);

PDFPageTree pages = vectorFile.requirePages();

int count = pages.getCount();

for(int i = 0; i < count; i++){
pdfPage = pages.getPage(i);

pdfDocument = pmmService.extractPages(pdfPage, 1,
PMMOptions.newInstance(PMMOptions.AllOptions),
PDFOpenOptions.newInstance());

tmpFile = File.createTempFile(asset.getName(), ".pdf");

tmpFileWriter = getTempFileWriter(tmpFile);

pdfDocument.save(tmpFileWriter, PDFSaveFullOptions.newInstance());

tmpFileWriter.close();

tmpFileReader = new FileInputStream(tmpFile);

AssetManager assetMgr = asset.getOriginal().getResourceResolver()
.adaptTo(AssetManager.class);

String folder = asset.adaptTo(Node.class).getParent().getPath();

assetMgr.createAsset( folder + "/" + asset.getName() + "-"
+ pdfPage.getPageNumber() + ".pdf",
tmpFileReader, "application/pdf", true);

pdfDocument.close();
tmpFileWriter.close();
tmpFileReader.close();
}
}catch(Exception e){
log.warn("Error generating pdf for - " + asset.getPath(), e);
}finally{
if (pdfDocument != null) {
pdfDocument.close();
}

if (tmpFileWriter != null) {
tmpFileWriter.close();
}

if(tmpFileReader !=null ){
tmpFileReader.close();
}

if(assetOrigIS != null){
assetOrigIS.close();
}
}
}

private static PDFDocument parseDocument(InputStream input) throws Exception {
ByteReader byteReader = null;
PDFDocument pdfDoc = null;

byteReader = new InputStreamByteReader(input);

try {
pdfDoc = PDFDocument.newInstance(byteReader, PDFOpenOptions.newInstance());
} catch (PDFException e) {
log.warn("Error while reading vector file", e);
throw e;
}

return pdfDoc;
}

private ByteWriter getTempFileWriter(File file) throws IOException {
file.delete();

File parent = file.getParentFile();

if (parent != null) {
parent.mkdirs();
}

file.createNewFile();

return new RandomAccessFileByteWriter(new RandomAccessFile(file, "rw"));
}

private Asset getAssetFromPayload(WorkItem item, Session session) {
Asset asset = null;

if(item.getWorkflowData().getPayloadType().equals("JCR_PATH")) {
String path = item.getWorkflowData().getPayload().toString();
Resource resource = getResourceResolver(session).getResource(path);

if(null != resource) {
asset = DamUtil.resolveToAsset(resource);
} else {
log.error("getAssetFromPaylod: asset [{}] in payload of workflow [{}] does not exist.", path, item.getWorkflow().getId());
}
}

return asset;
}

private ResourceResolver getResourceResolver(final Session session) {
return jcrResolverFactory.getResourceResolver(session);
}
}


2) #85 to #106 loop through pages, write the page stream to a temp file and create pdf asset by reading from the temp file

3) For compilation, Gibson libraries (com.adobe.internal.pdftoolkit) are not available on Adobe public maven repo Nexus; so create a private repo - eaemrepo and add the location in repositories section of project pom.xml (the jars can be found in CQ install eg. authorcrx-quickstartlaunchpadfelix undle446datainstallpdfcore-3.0.568820.jar or you can get them from this samples source code)

 <repositories>
<repository>
<id>eaemrepo</id>
<name>Experience AEM Internal Repo</name>
<url>file://${project.basedir}/../libs</url>
</repository>

<repository>
<id>adobe</id>
<name>Adobe Public Repository</name>
<url>http://repo.adobe.com/nexus/content/groups/public/</url>
<layout>default</layout>
</repository>
</repositories>


4) Add the Process step apps.experienceaem.pdf.CreatePDFRendition to DAM Update Asset workflow. For demonstration purposes, the workflow step was added to ootb DAM Update Asset workflow (/etc/workflow/models/dam/update_asset), but in real world it is always recommended to copy and create a new workflow model for adding any additional workflow steps






visit link download