ColdFusion: Create PDF from multiple PDF blobs - pdf

I have multiple pdfs stored in my database as blobs and I need to merge them to create a single pdf that needs to be streamed to the user.
I understand that it is fairly easy to do this if I am rendering a single pdf from blob, but I cannot figure how to merge multiple blobs.
<cfheader name="Content-Disposition" value="inline; filename=#document.name#.#document.ext#">
<cfcontent type="application/pdf" variable="#document.content#">
I see that CFPDF helps with this functionality, but cant seem to be able to get my blob into a cfpdf variable. A similar question has been asked here before, but it doesnt have the answer I seek.
Thanks!

Try converting the blob data to a file (in-memory using ram:// if possible to save writing to disk) and then use that as the cfpdf merge source. You can do it for each blob as you loop over your query within the cfpdf action="merge" tag:
<cfquery name="q" datasource="test">
SELECT content FROM pdfs
</cfquery>
<cfpdf action="merge" name="mergedPdf">
<cfloop query="q">
<cfset tempBinary=q.content><!---intermediate var seems to be necessary in some environments --->
<cffile action="write" output="#tempBinary#" file="ram://temp.pdf">
<cfpdfparam source="ram://temp.pdf">
</cfloop>
</cfpdf>
<cfcontent type="application/pdf" variable="#ToBinary( mergedPdf )#" reset="true">
Note you can use a single temp file - no need to create a different one for each blob in the query.

I think you can do the following
Retrieve each pdf blob stored in db and create pdf using cfpdf and store them in some temp directory
<cfpdf action="write" destination="c:\pdfs\1.pdf" source="#mypdfblob1" >
Retrieve all such blobs and store them as pdfs in the temp directory
Merge all those pdfs using cfpdf merge by specifying the temp directory in cfpdf merge
<cfpdf action="merge" directory="C:\pdfs" destination="C:\result.pdf">

Related

Converting SQL Binary Content to File

I have a SQL Server database that is storing the contents of files in a table. Specifically, there are 2 fields:
Contents: varbinary(max) field that always starts with '0x1F.....'
FileType: varchar(5) field that has the type of file, such as PDF, docx, etc.
How can I convert the contents back into a file? I am trying to use Coldfusion, if that is possible, to convert it. If not, what are the steps to convert the binary into a file?
I tried the following (assuming a docx filetype) but it didn't produce a valid word file:
<cfset DecodedValue = BinaryDecode(contents,"hex")>
<cffile action="WRITE" output="#DecodedValue#" file="C:\decodedfile.docx">
Thanks to User Ageax, the first 4 size bytes of 31,-117,8,0 show the content is stored in GZIP format instead.
I first save the content as a gzip then extract the file. My code is as follows:
<cfquery name="getfile" datasource="tempdb">
select content from table
</cfquery>
<cfset FileWrite("C:\mygzipfile.gzip", getfile.content)>
To extract gzip to a file using coldfusion, I used the solution at: http://coldfusion-tip.blogspot.com/2012/04/unzip-gz-file-in-coldfusion.html
tldr;
The data is already binary, so ditch the binaryX() functions and save the content directly to a file. Read the first few bytes of the binary to verify the file type. In this case, turns out the document was actually stored in GZIP format, not raw DOCX.
Don't be misled by how SSMS chooses to display it. SSMS displays binary in user friendly hex format, but it's still stored as binary. Just write the binary directly to the file, without any BinaryX functions.
<cfset FileWrite("C:\decodedfile.docx", contents)>
Also, check your DSN settings and ensure the "BLOB - Enable binary large object retrieval (BLOB)" setting is enabled, so binary values aren't truncated at 64K (default buffer size).
Update 1:
The FileWrite() code above works correctly IF the "contents" column contains the binary of a valid .docx file. Perhaps the data is being stored differently than we're thinking? Run a query to retrieve the binary of a single document and output the first four bytes. What is the result? Typically, the first four bytes of .docx files should be 80, 75, 3, 4.
<!--- print size and first 4 bytes --->
<cfoutput>
size in bytes = #arrayLen(qYourQuery.contents)#<br>
<cfloop from="1" to="4" index="x">
byte #x# = #qYourQuery.contents[1][x]#<br>
</cfloop>
</cfoutput>
Update 2:
Closest I could find to 1F 8B 08 is GZIP. Try using probeContentType() on the saved file. What does it report?
<cfscript>
paths = createObject("java", "java.nio.file.Paths");
files = createObject("java", "java.nio.file.Files");
input = paths.get("c:/yourFileName.docx", []);
writeDump(files.probeContentType(input));
</cfscript>

Appending PDF to Existing PDF in cold fusion 11

I am using Cold fusion 11.
I want to append a PDF to an existing PDF and want to generate approximately 30 pages like this e.g. I have a PDF with with 20 pages and I want to append 5 more pages to it.
You can use cfpdf tag with merge as action to accomplish it.Like this
<cfpdf action="merge" destination="finalMergedPDF.pdf" overwrite="yes">
<cfpdfparam source="pdf_20_pages.pdf">
<cfpdfparam source="pdf_5_pages.pdf">
</cfpdf>
You can also specify specific pages or range of pages while merging pdf files in cfpdfparam. Like this.
<cfpdfparam source="file3.pdf" pages="10-20">
<cfpdfparam source="file4.pdf" pages="25,35,42">
Refer this

how to check and download corrupted pdf files using coldfusion?

<cfif isPDFFile("book.pdf")>
Not corrupted!<br/>
<cfelse>
Corrupted pdf file!
</cfif>
I'm new to coldfusion. Can anybody help me how to check and download corrupted pdf files using coldfusion.
if book.pdf is corrupted one then isPDFFile() returns false (i.e this function returns that book.pdf is not a pdf file). So,can we use this point for checking if a pdf file is corrupted or not?
Is this the right way to do? If not,what's the right way and how to download those corrupted pdf files?
ColdFusion's isPDFfile function already returns if the file is invalid or corrupt. But you may want to distinguish between the cause of the return value:
<cfset pdfFileLocation = "book.pdf">
<cfif (not isSimpleValue(pdfFileLocation)) or (not len(pdfFileLocation))>
<cfoutput>File's location is invalid.</cfoutput>
<cfelseif not fileExists(pdfFileLocation)>
<cfoutput>File not found on location #htmlEditFormat(pdfFileLocation)#.</cfoutput>
<cfelseif not isPDFfile(pdfFileLocation)>
<cfoutput>File is either not a PDF document or its content is damaged.</cfoutput>
<cfelse>
<cfoutput>File is a valid PDF document.</cfoutput>
</cfif>
What do you mean with "download"? In your example, you already have the file book.pdf in the current directory (relative path). If you want to repair the document, use ColdFusion's fileReadBinary function to inspect the binary data. Repairing PDF isn't exactly a child's play though.

Taking 2 PDF images and putting them together in a single PDF page?

I am trying to take two PDF images and merging them onto one PDF page. The reason it has to be in PDF is because JPG is lossy and will not generate a crisp image for print. Is their a way in Coldfusion 9 to merge these 2 PDF images?
Note: I did find a plugin for photoshop that supposedly makes JPG lossless. CFIMAGE will be able to do my task without a problem if that's the case. I want to see if CFPDF has some trick that I do not know about first before I go and explore this lossless JPG option.
Ok so I think I figured it out...
Trying to manipulate PDF files onto a single page is NOT possible. I found CF9 CFIMAGE tag supports TIFF format which is lossless. So using 2 TIFF sources files VS 2 PDF source files allows me to use CFIMAGE to manipulate the lossless TIFF files
<cfimage source="#APPLICATION.config.serverpath#/background.tif" name="Background">
<cfimage source="#APPLICATION.config.serverpath#/ad1.tif" name="ad1">
<cfimage source="#APPLICATION.config.serverpath#/ad2.tif" name="ad2">
<cfset height1 = ImageGetHeight(ad1)>
<cfset width1 = ImageGetWidth(ad1)>
<cfset height2 = ImageGetHeight(ad2)>
<cfset width2 = ImageGetWidth(ad2)>
<cfset resImage1 = ImageCopy(ad1,0,0,width1,height1)>
<cfset resImage2 = ImageCopy(ad2,0,0,width2,height2)>
<cfset ImagePaste(Background,resImage1,0,0)>
<cfset ImagePaste(Background,resImage2,0,height1)>
<cfimage source="#Background#"
action="write"
destination="#APPLICATION.config.serverpath#/test.tif"
overwrite="yes">
<cfdocument format="pdf" name="temp">
<img src="test.tif">
</cfdocument>
<cffile action="write"
file="#APPLICATION.config.serverpath#/test.pdf"
output="#temp#">
to generate the final PDF.

Can I include another PDF in CFDOCUMENT?

I have a PDF generated in Coldfusion. I would like to add pages from another PDF sitting in the folder.
I've checked cfpdf, but it doesn't seem to be the way to go.
Is there a way to do this?
<cfdocument format="PDF" fontEmbed = "yes" pageType="A4" margintop="0.2" marginbottom="0.1" marginleft="0.2" marginright="0.2">
<cfinclude template="header.inc">
... content ....
pages 2nd PDF should be here
</cfdocument>
Here in its simplest form is how to append an existing PDF on disk to a dynamically created PDF and serve it to the browser without writing anything new to the physical or virtual file system.
<!--- Create a new PDF and store it in a variable called newPdf --->
<cfdocument format="PDF" name="newPdf">
Content of new PDF here. Content of an existing PDF to be appended below.
</cfdocument>
<!--- Append to the new PDF the contents of the existing PDF located in the same folder as this script and store it in a variable called mergedPdf --->
<cfpdf action="merge" name="mergedPdf">
<cfpdfparam source="newPdf">
<cfpdfparam source="existing.pdf">
</cfpdf>
<!--- Output the merged PDF to the browser --->
<cfcontent type="application/pdf" variable="#ToBinary( mergedPdf )#" reset="true">
(You might want to add a <cfheader> to suggest how the PDF should be handled by the browser, ie inline or attachment.)
Take a look at the action="merge" attribute of cfpdf.