Expand my Community achievements bar.

Download Document of Record PDF with Form Data with Button In Adaptive Form

Avatar

Level 4

Hello,

 

I currently have a use case where the user fills in the adaptive form and should be able to download the Document of Record PDF (XDP template) with the form data by clicking a button. The purpose of this use case is so the entered data is not stored in AEM or a database, so the adaptive form only serves as a form filler.

 

From my initial findings, there is a Java API you can use to generate the DoR:

https://helpx.adobe.com/experience-manager/6-3/forms/javadocs/com/adobe/aemds/guide/addon/dor/DoRSer...

 

What would be the best way to implement this API for use in an adaptive form? I would like this to be used for a majority of my forms. Thank you

17 Replies

Avatar

Employee Advisor

@techddx Please refer to the snippet provided here[0].

This sample uses the same "com.adobe.aemds.guide.addon.dor.DoROptions" class you were referring previously. This help doc also provides relevant packages/configs, so should suffice your requirement. 

 

 

[0] - https://experienceleague.adobe.com/docs/experience-manager-learn/forms/adaptive-forms/document-of-re... 

Avatar

Level 4
Hi @Pulkit_Jain_, thank you for this document. I tried the sample implementation, but found the resulting PDF is saved in the AEM CRX under "/content/usergenerated/content/aemformsenablement". Is there a way to only provide the download to the PDF, and not save the PDF within AEM CRX?

Avatar

Employee Advisor
you will have to modify the code to stream the pdf back to the browser

Avatar

Employee Advisor

@techddx 

To stream the pdf back to the browser, you may have to add the below piece here[0]. 

byte[] byteInfo = dorResult.ToArray();
dorResult.Write(byteInfo, 0, byteInfo.Length);
dorResult.Position = 0;
HttpContext.Response.AddHeader("content-disposition","inline; filename=form.pdf"); //for browser rendering
return new FileStreamResult(dorResult, "application/pdf");

 [0] - https://experienceleague.adobe.com/docs/experience-manager-learn/forms/adaptive-forms/document-of-re... 

Avatar

Level 4

Hi @Pulkit_Jain_, thank you for your help.

 

I added the following code to the POST.jsp, but the PDF download is not appearing in the browser. I checked the logs and there are no errors either.

 

	Session session;
    com.adobe.aemds.guide.addon.dor.DoRService dorService = sling.getService(com.adobe.aemds.guide.addon.dor.DoRService.class);
	System.out.println("Got ... DOR Service");
	com.mergeandfuse.getserviceuserresolver.GetResolver aemDemoListings = sling.getService(com.mergeandfuse.getserviceuserresolver.GetResolver.class);
	System.out.println("Got aem DemoListings");
	resourceResolver = aemDemoListings.getFormsServiceResolver(); // used to resolve the template path
	session = resourceResolver.adaptTo(Session.class);
	resource = resourceResolver.getResource(templatePath);
	com.adobe.aemds.guide.addon.dor.DoROptions dorOptions =  new com.adobe.aemds.guide.addon.dor.DoROptions();
	dorOptions.setData(dataXml);
	dorOptions.setFormResource(resource);
	java.util.Locale locale = new java.util.Locale("en");
	dorOptions.setLocale(locale);
	com.adobe.aemds.guide.addon.dor.DoRResult dorResult = dorService.render(dorOptions);
	byte[] fileBytes = dorResult.getContent();
	com.adobe.aemfd.docmanager.Document dorDocument = new com.adobe.aemfd.docmanager.Document(fileBytes); // DoR

	// Output Service Testing
	java.util.Random r1 = new java.util.Random();
	String randomName = Long.toString(Math.abs(r1.nextLong()), 36);
	String fileName = formName + " - " + currentDate + " - " + randomName +".pdf";
	File pdfFile = new File(fileName);
	dorDocument.copyToFile(pdfFile);
	response.setContentType("application/octet-stream");
	response.setContentLength((int) pdfFile.length());
	response.setHeader( "Content-Disposition",String.format("inline; filename=\"%s\"", pdfFile.getName()));
	FileInputStream fis = new FileInputStream(pdfFile);
	byte[] buffer = new byte[(int)pdfFile.length()];
	fis.close();
	ServletOutputStream os = response.getOutputStream();
    os.write(buffer);
    os.close();

 

Avatar

Level 1
Thank you so much for your help. Keep doing what you do my great man

Avatar

Level 4

I have created a servlet based on the DoR with API implementation with JSP. However when deploying the bundle, the servlet component is in the "satisfied" state. How can I get it to activate? Below is the servlet code:

 

 

public class StreamPDF extends SlingAllMethodsServlet{
	private static final long serialVersionUID = 1L;
	
	@SlingObject
    private ResourceResolver resourceResolver;
	@SlingObject
	private Resource resource;
	
	//OSGi Services
	@Reference
	private com.adobe.aemds.guide.addon.dor.DoRService dorService;
	@Reference
	private GetResolver AEMResourceResolver;
	
	protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException{
	    performTask(request, response);
	  }
	
	protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException{
		performTask(request, response);
	}
	
	private void performTask(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
		try {
			String dataXml = request.getParameter("data");
			// get path to DoR template from xml
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder;
			builder = factory.newDocumentBuilder();
			org.w3c.dom.Document doc = builder.parse(new InputSource(new StringReader(dataXml)));
			XPath xPath = XPathFactory.newInstance().newXPath();
			String templatePath = xPath.compile("//templatePath").evaluate(doc);
			String formName = xPath.compile("//formName").evaluate(doc);
			
			// get current date for filename
			SimpleDateFormat sdf = new SimpleDateFormat("MM.dd.yy");
			String currentDate = sdf.format(new Date());
			
			// Begin generate DoR
			Session session;
			resourceResolver = AEMResourceResolver.getFormsServiceResolver();
			session = resourceResolver.adaptTo(Session.class);
			resource = resourceResolver.getResource(templatePath);
			// dorService
			com.adobe.aemds.guide.addon.dor.DoROptions dorOptions =  new com.adobe.aemds.guide.addon.dor.DoROptions();
			dorOptions.setData(dataXml);
			dorOptions.setFormResource(resource);
			java.util.Locale locale = new java.util.Locale("en");
			dorOptions.setLocale(locale);
			com.adobe.aemds.guide.addon.dor.DoRResult dorResult = dorService.render(dorOptions);
			byte[] fileBytes = dorResult.getContent();
			com.adobe.aemfd.docmanager.Document dorDocument = new com.adobe.aemfd.docmanager.Document(fileBytes); // DoR
			java.util.Random r1 = new java.util.Random();
			String randomName = Long.toString(Math.abs(r1.nextLong()), 36);
			String fileName = formName + " - " + currentDate + " - " + randomName +".pdf";
			InputStream fileInputStream = dorDocument.getInputStream();
			dorDocument.close();
			response.setContentType("application/pdf");
			response.addHeader("Content-Disposition", "attachment; filename=" + fileName);
			response.setContentLength(fileInputStream.available());
			ServletOutputStream servletOutputStream = response.getOutputStream();
			int bytes;
			while ((bytes = fileInputStream.read()) != -1) {
		        servletOutputStream.write(bytes); 
			}
		      servletOutputStream.flush();
		      servletOutputStream.close();

		} catch (ParserConfigurationException e) {	
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		} catch (DoRGenerationException e) {
			e.printStackTrace();
		}

	}
}

 

 

Avatar

Level 4
I checked the error log and found this: *ERROR* [FelixDispatchQueue] org.apache.sling.servlets.resolver FrameworkEvent ERROR (org.osgi.framework.ServiceException: Service factory exception: Could not load implementation object class dgs.aem.core.servlets.StreamPDF) org.osgi.framework.ServiceException: Service factory exception: Could not load implementation object class dgs.aem.core.servlets.StreamPDF

Avatar

Level 4

Issue was resolved, it was due to another bundle deployed with the same groupId and it had to be uninstalled.

Avatar

Level 4

The servlet is working and the PDF is being generated with a button ajax call. However the generated PDF is corrupt. Here is my code in the button:

 

/**
* Get pdf
* @Return {OPTIONS} drop down options 
 */
function getPdf()
{
    console.log("in view pdf");
    window.guideBridge.getDataXML(
        {
        	success: function(result) {
             var formData = new FormData();
             formData.append("dataXml",result.data);
			console.log("got data"+result.data);
           	var settings ={
            				"async": true,
							"url": "/bin/streampdf",
							"method": "POST",
                			data:{'data':result.data},
   						}
            $.ajax(settings).done(function(response)
            {
                console.log("got response from POST");
				var file = new Blob([response], {
                type : 'application/pdf'
                });
                var fileURL = URL.createObjectURL(file);

                var a         = document.createElement('a');
                a.href        = fileURL; 
                a.target      = '_blank';
                a.download    = 'form.pdf';
                document.body.appendChild(a);
                a.click();
            })

    	},
    	error:function(guideResultObject) {console.log("got error"); },
        guideState : null,
        boundData  : true});

}

Avatar

Level 9

Save the pdf to local file system after it is generated 

Avatar

Level 4
I am testing by saving it to local system first, and the PDF is successfully generated. However, when trying to get the file from button AJAX call, the PDF is corrupt.

Avatar

Employee
Your Adaptive Form is based on the XDP template? and you are able to merge the data with the xdp template using the DoR API. Can you please confirm?

Avatar

Level 4
Yes, the adaptive form is based on an XDP template and the data is being merged with the DoR API. I was able to resolve my issues and generate a functional PDF. I will share my solution shortly.