Creating PDF thumbnails with Lucee has been broken since version 5, and possibly longer.
https://dev.lucee.org/t/cfpdf-action-thumbnail-not-working-on-lucee-5/1389
https://luceeserver.atlassian.net/browse/LDEV-967
Here is a function that should help you if you really need to get it working.
UPDATE: Please see Brad Wood's new solution in the Comments section, which works with new versions of Lucee.
<cfscript> // Creates a jpg thumbnail from a PDF file // thumbnailFromPDF() // returns the file name of the JPG that it creates. // arguments // - pdfFile (required), This is the physical file path to the PDF // - destination (optional), Location to save the thumbbail, defaults to same location as original. // - width (optional), width of the resulting image, defaults to 200px // - page (optional), page number to use for the thumbnail, defaults to page 1. function thumbnailFromPDF(required string pdfFile,string destination = '',string width = '200', string page = 1) { // Java libraries needed var BufferedImage = createObject("java","java.awt.image.BufferedImage"); var ImageWriter = createObject("java","org.apache.pdfbox.util.PDFImageWriter"); // load the pdf into PDFBox var document = createObject("java","org.apache.pdfbox.pdmodel.PDDocument").load("#arguments.pdffile#"); // get the base paths file names needed var basefile = listlast(arguments.pdffile,server.separator.file); var basefilename = replacenocase(basefile,".pdf","","ALL"); var basepath = replacenocase(arguments.pdfFile,basefile,""); if (arguments.destination IS '') { arguments.destination = basepath; } if (right(arguments.destination,1) Neq server.separator.file) { arguments.destination = arguments.destination & server.separator.file; } var returnfileprefix = "#arguments.destination##basefilename#_"; //includes dest path var returnfilename = "#basefilename#_#arguments.page#.jpg"; //check file extension if (right(arguments.pdfFile,4) Neq ".pdf") { cfthrow(message="File does not appear to be a PDF file."); } //write the image of page 1. This writes a file called 1.jpg. There is prefix argument and in this case we use the file name as the prefix. // arguments... writeImage(document,image type,start page, end page, prefix to <page number>.jpg, java color profile, resolution) imageWriter.writeImage(document, JavaCast("string","jpg"), JavaCast("string",""), arguments.page, arguments.page, JavaCast("string",returnfileprefix), BufferedImage.TYPE_INT_RGB, 200); // close document object, no longer needed document.close(); // resize the image cfimage(action="resize",source="#arguments.destination##returnfilename#",destination="#arguments.destination##returnfilename#",overwrite="true",width=arguments.width); return returnfilename; }; </cfscript>
Example of how to use this…
<cfscript> pdfFile = "c:\path\to\my\file\name.pdf"; // make a thumbnail of page 1 in the images folder, with a width of 50 thumbnail = thumbnailFromPDF(pdffile,expandpath('/images'),50,1); </cfscript> <cfoutput><img src="/images/#thumbnail#" /></cfoutput>
Hopefully the Lucee team will fix cfpdf and this won’t be necessary in the future.
Great stuff. Just a few suggestions.
1) Add PDDocument.close(); and document.close(); after imageWriter.writeImage. (You can workaround the first one by skipping var PDDocument… and using var document = createObject(“java”,”org.apache.pdfbox.pdmodel.PDDocument”).load(“#arguments.pdffile#”); instead.)
2) Use server.separator.file instead of “\” so that it works on Windows and Unix-based systems.
@Juan – Great suggestions! I have incorporate both of them and updated the post.
Great Work! Thaks so much!
Thank you for this – can you believe they’ve not fixed it yet???
This is a great start, thank you for putting this together. Unfortunately, it does not seem to work when there are embedded fonts in the PDF. The text will be missing when rendering the image.
I was looking for a workaround by possibly using `org.apache.pdfbox.rendering.PDFRenderer`, but it does not seem to be included anymore.
When I wrote this, it was intended to be a stopgap while Lucee fixed the issue. It is a limited solution, and you are correct that it will not work with embedded fonts. Unfortunately, almost five years later the Lucee bug is not resolved.
Here is a new version that takes into account the current PDFBox version in Lucee:
/** Creates a jpg thumbnail from a PDF file
*
* @pdfFile This is the physical file path to the PDF or a byte array (binary) representing a loaded PDF
* @destination Location to save the thumbbail, defaults to same location as original.
* @width width of the resulting image, defaults to 200px
* @page page number to use for the thumbnail, defaults to page 1.
* @imagePrefix A string to prefix to the image name
*
* @returns The file name of the JPG that it creates.
*/
function thumbnailFromPDF( required pdfFile, string destination=”, string width=’200′, string page=1, string imagePrefix=”) {
// get the base paths file names needed
if( isBinary( pdffile ) ) {
var basefile = ‘thumbnail’;
var loadSource = pdffile;
} else {
if (right(arguments.pdfFile,4) Neq “.pdf”) {
cfthrow(message=”File does not appear to be a PDF file.”);
}
if (arguments.destination IS ”) {
arguments.destination = getDirectoryFromPath( arguments.pdfFile );
}
var basefile = listlast(arguments.pdffile,server.separator.file);
var loadSource = createObject( ‘java’, ‘java.io.File’ ).init( pdffile );
}
// load the pdf into PDFBox
var document = createObject(“java”,”org.apache.pdfbox.Loader”).loadPDF( loadSource );
try {
var ImageWriter = createObject(“java”,”org.apache.pdfbox.rendering.PDFRenderer”).init( document );
var basefilename = replacenocase(basefile,”.pdf”,””,”ALL”);
if (right(arguments.destination,1) Neq server.separator.file) {
arguments.destination = arguments.destination & server.separator.file;
}
var returnfileprefix = “#arguments.destination##imagePrefix##basefilename#_page_”; //includes dest path
var returnfilename = “#imagePrefix##basefilename#_page_#arguments.page#.jpg”;
//write the image of page 1. This writes a file called 1.jpg. There is prefix argument and in this case we use the file name as the prefix.
// arguments… writeImage(document,image type,start page, end page, prefix to .jpg, java color profile, resolution)
var BufferedImage = imageWriter.renderImage(arguments.page-1);
} finally {
// close document object, no longer needed
document.close();
}
// resize the image
cfimage(action=”resize”,source=BufferedImage,destination=”#arguments.destination##returnfilename#”,overwrite=”true”,width=arguments.width);
return returnfilename;
}