Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2018 (Hollywood, CA) with: Azeez Olaniran and Adebayo Maborukoje and Jorg Are
Ben Nadel at InVision In Real Life (IRL) 2018 (Hollywood, CA) with: Azeez Olaniran Adebayo Maborukoje Jorg Are

Using Both SrcFile And CFDocumentItem In The Same CFDocument Tag In Lucee CFML 5.3.7.47

By
Published in Comments (1)

At InVision, we generate a surprising number of PDF documents. For the most part, the CFDocument tag in Lucee CFML just works. But, sometimes, PDF generation eats-up all the RAM and an OOM (Out of Memory) error is thrown. As such, I'm always on the lookout for ways to tweak the PDF generation process to see if I can consume fewer resources. One idea that I had was to pre-generate the HTML file instead of just rendering the HTML content within the CFDocument tag-body. But, I wasn't sure if I could combine the concept of the srcfile attribute with the child-tag, CFDocumentItem. As such, I wanted to try it out in Lucee CFML 5.3.7.47.

CAUTION: My goal here is to try and find ways to consume fewer resources while generating a PDF. That said, I am not saying that this technique uses fewer resources. This post is simply an exploration of the mechanics of this technique, not the performance of this technique.

Historically, when I've gone to generate a PDF document with the CFDocument tag, I just jam a whole bunch of CFML right into the body of the tag:

<cfscript>

	document
		format = "pdf"
		filename = "my-doc.pdf"
		overwrite = true
		{

		```
		<p>
			I can haz PDF?!
		</p>
		```

	}

</cfscript>

This example is obviously trivial - in a real-world PDF, the content of the document would be significantly more complex and would (likely) include CFDocumentSection and CFDocumentItem tags. But, part of me wonders if all of that "child logic" is contributing to the memory consumption. As such, I'm curious to see if using an external file via the SrcFile attribute would:

  1. Force me to simply the mechanics of the document.

  2. Allow the PDF-generation engine to keep less "stuff" in memory.

Of course, I still need to define a document header (in some cases); and, I can't find a way to do this with just HTML/CSS; so, I'll still need the CFDocumentItem tag to be a child of the CFDocument tag.

Here's my test to see if this works - the following code pre-generates an HTML file by rendering a CFML file to a string-buffer and then writing that buffer to disk. This generated-file is then consumed by the CFDocument tag as the SrcFile attribute:

<cfscript>

	stub = "./out/doc-#createUniqueId()#";

	// Evaluate the CFML body that we're going to use for the PDF generation.
	savecontent variable = "bodyContent" {
		include "./render-body.cfm";
	}

	// Save the CFML document as a static HTML document. This is what we're going to use
	// as the "srcfile" for the CFDocument tag.
	fileWrite( "#stub#-body.html", bodyContent );

	document
		format = "pdf"
		filename = "#stub#.pdf"
		srcfile = "#stub#-body.html"
		overwrite = true
		localurl = true
		{

		// Note that we can mix both "srcfile" and CFDocumentItem techniques.
		documentItem type = "header" {
			```
			<table width="100%" cellpadding="0" cellspacing="0" class="page-header">
			<tr>
				<td class="page-header__left">
					Testing CFDocument
				</td>
				<td class="page-header__right">
					SrcFile &amp; DocumentItem(s)
				</td>
			</tr>
			</table>
			```			
		}

	}

</cfscript>

As you can see, the only child content of the CFDocument tag is the one CFDocumentItem tag for the header - the rest of the body content is taken from the srcfile attribute. And, when we run this ColdFusion code, we are able to successfully generate a PDF document using both sources of content:

A PDF document generated with CFDocument srcfile and CFDocumentItem in Lucee CFML.

Again, I have no idea if this actually has any impact on resource consumption. But, now that I know that this approach is possible, it gives me something more to play with. Generating PDFs in ColdFusion isn't always "great"; but, by gosh, they make it easy.

Want to use code from this post? Check out the license.

Reader Comments

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel