我正在使用ColdFusion和iText生成PDF文档,我希望能够在iText决定进行分页时“自动”向PDF添加页眉和页脚。 我已经看到了如何在Java中执行此操作的示例,以下是执行此操作的基本方法:
public class MyHeaderFooterPageEvent extends PdfPageEventHelper {
public void onEndPage(PdfWriter writer, Document document) {
//add your content here
}
}
然后,在开始撰写PDF文档之前,您将“注册”您的活动,如:
MyHeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
(至少据我所知。)
我已成功设法将类PdfPageEventHelper加载到ColdFusion中,所以我知道它在那里:
<cfset local.PdfPageEventHelper=CreateObject("java","com.lowagie.text.pdf.PdfPageEventHelper")>
当我转储local.PdfPageEventHelper时,我得到:
那么如何在调用onEndPage时告诉ColdFusion该怎么做,以及如何注册该事件以便调用它?
我在Linux服务器上使用Coldfusion 11。
答案 0 :(得分:1)
此解决方案主要基于this old blog post at cfSearching.blogspot.se。
虽然该解决方案使用 javaloader动态代理库,但此解决方案使用较新的(?)函数CreateDynamicProxy(我认为可以从ColdFusion 10获得), Ageax (非常感谢!)让我意识到了。
已在Linux服务器上的 ColdFusion 11 中成功测试。
自己尝试一下:
cfm文件的内容:
<!---call function--->
<cfset _createPdf()>
<!---function for creating pdf with footer that is created via an event handler in onEndPage--->
<cffunction name="_createPdf" output="no" returntype="void">
<cfargument name="pdfFile" type="string" default="document.pdf" hint="the file name to write to disc">
<cfargument name="writeToBrowser" type="boolean" default="true" hint="will open the pdf document in the browser and delete the file when done">
<cfscript>
//set filePath for document
local.filePath = ExpandPath('.')&"/"&arguments.pdfFile;
//get BaseFont
local.BaseFont = CreateObject("java", "com.lowagie.text.pdf.BaseFont");
//get CMYK color
local.CMYKColor = CreateObject("java", "com.lowagie.text.pdf.CMYKColor");
//create color
local.color = local.CMYKColor.init(JavaCast("int",0),JavaCast("int",0),JavaCast("int",0),JavaCast("int",256));
//create font
local.font = local.BaseFont.createFont(local.BaseFont.COURIER, local.BaseFont.CP1252, true);
//compose custom config to make accessable in PdfPageEventHandler.cfc
local.config = {myCustomFooter = {text = "Page number", color = local.color, font = local.font, size = 20}};
//init the event handler (make sure the PdfPageEventHandler.cfc is present in the same folder as this template)
local.eventHandler = CreateObject("component", "PdfPageEventHandler").init(config = local.config);
//we can pass in an array of strings which name all the interfaces we want out dynamic proxy to implement
local.interfaces = ["com.lowagie.text.pdf.PdfPageEvent"];
//create a dynamic proxy that we will pass to the iText writer
local.eventHandlerProxy = CreateDynamicProxy(local.eventHandler, local.interfaces);
//init success flag
local.success = true;
try {
//init document
local.document = CreateObject("java", "com.lowagie.text.Document").init();
//init outstream
local.outputStream = CreateObject("java", "java.io.FileOutputStream").init(local.filePath);
//init writer
local.writer = CreateObject("java", "com.lowagie.text.pdf.PdfWriter").getInstance(local.document, local.outputStream);
//register the PROXY as the page event handler
local.writer.setPageEvent(local.eventHandlerProxy);
//open document
local.document.open();
//init paragraph
local.paragraph = CreateObject("java", "com.lowagie.text.Paragraph");
//output some pages with a simple text message. NOTE that our eventHandler will take care of adding footers on every page - that's the whole point with this example by the way :)
for (local.i = 1; local.i lte 3; local.i = local.i + 1) {
//add paragraph with text
local.document.add(local.paragraph.init("This page should have a footer with a page number on it!"));
//trigger new page
local.document.newPage();
}
} catch (any e) {
//an error occured
WriteOutput("Error: " & e.message);
//set success flag to false
local.success = false;
}
if (StructKeyExists(local, "document")) {
//close document
local.document.close();
}
if (StructKeyExists(local, "outStream")) {
//close outStream
local.outputStream.close();
}
if (local.success && arguments.writeToBrowser) {
_openPdf(filePath=local.filePath);
}
</cfscript>
</cffunction>
<!---function for opening pdf in browser--->
<cffunction name="_openPdf" output="no" returntype="void">
<cfargument name="filePath" type="string" required="yes">
<cfcontent type="application/pdf" file="#arguments.filePath#" deletefile="yes">
</cffunction>
cfc文件的内容,应命名为 PdfPageEventHandler.cfc :
<cfcomponent output="false" hint="iText Event handler used to add headers, footers, etc.">
<!---1. INIT FUNCTION--->
<cffunction name="init" access="public" returntype="PdfPageEventHandler" output="false">
<!---come up with your own arguments that you want to have access to in onEndPage etc--->
<cfargument name="config" type="any" required="true" hint="custom config" />
<!---make sure the config is accessable by other functions--->
<cfset variables.config = arguments.config>
<cfreturn this />
</cffunction>
<!---2. ON END PAGE - the function that is in focus in this example--->
<cffunction name="onEndPage" access="public" returntype="void" output="true" hint="Called when a page is finished, just before being written to the document.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---edit below to make your own header / footer--->
<cfscript>
local.cb = arguments.writer.getDirectContent();
local.cb.saveState();
local.cb.beginText();
local.cb.setColorFill(variables.config.myCustomFooter.color);
local.cb.setFontAndSize(variables.config.myCustomFooter.font, variables.config.myCustomFooter.size);
local.cb.setTextMatrix(arguments.document.left(), arguments.document.bottom() - 10);
local.text = "#variables.config.myCustomFooter.text# #arguments.writer.getPageNumber()#";
local.cb.showText(local.text);
local.cb.endText();
local.cb.restoreState();
</cfscript>
</cffunction>
<!---3. OTHER FUNCTIONS THAT MUST EXIST (at least in this example)--->
<cffunction name="onOpenDocument" access="public" returntype="void" output="false" hint="Called when the document is opened.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when the document is opened--->
</cffunction>
<cffunction name="onCloseDocument" access="public" returntype="void" output="false" hint="Called when the document is closed">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when the document is closed--->
</cffunction>
<cffunction name="onStartPage" access="public" returntype="void" output="false" hint="Called when a page is initialized.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when a page is initialized--->
</cffunction>
<cffunction name="onParagraph" access="public" returntype="void" output="false" hint="Called when a Paragraph is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<!---To be implemented: Code called when paragraph is written --->
</cffunction>
<cffunction name="onParagraphEnd" access="public" returntype="void" output="false" hint="Called when a Paragraph is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<!---To be implemented: Code called on end of paragraph is written--->
</cffunction>
<!---4. FUNCTIONS THAT ONLY NEEDS TO EXIST IF YOU DO SOMETHING THAT TRIGGERS THEM
<cffunction name="OnChapter" access="public" returntype="void" output="false" hint="Called when a Chapter is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="title" type="any" required="true" hint="Title of the chapter. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when a Chapter is written--->
</cffunction>
<cffunction name="onChapterEnd" access="public" returntype="void" output="false" hint="Called when the end of a Chapter is reached">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="position" type="numeric" required="true" hint="The position of the end of the chapter. Value is a java float" />
<!---To be implemented: Code called when the end of a Chapter is reached--->
</cffunction>
<cffunction name="onGenericTag" access="public" returntype="void" output="false" hint="Called when a Chunk with a generic tag is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="rect" type="any" required="true" hint="The Rectangle containing the Chunk. Instance of com.lowagie.text.Rectangle" />
<cfargument name="text" type="string" required="true" hint="The text of the tag" />
<!---To be implemented: Code called when a Chunk with a generic tag is written--->
</cffunction>
<cffunction name="onSection" access="public" returntype="void" output="false" hint="Called when a Section is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="depth" type="numeric" required="true" hint="The number depth of the Section. Value is a java int" />
<cfargument name="title" type="any" required="true" hint="Title of the section. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when a Section is written--->
</cffunction>
<cffunction name="onSectionEnd" access="public" returntype="void" output="false" hint="Called when the end of a Section is reached.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="depth" type="numeric" required="true" hint="The number depth of the Section. Value is a java int" />
<cfargument name="title" type="numeric" required="true" hint="Title of the section. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when the end of a Section is reached--->
</cffunction>
--->
</cfcomponent>
<强>更新<!/强>
这里有相同的cfc,但在纯cfscript中,对你而言更喜欢:
<cfscript>
component output="false" hint="iText Event handler used to add headers, footers, etc." {
property name="config" type="struct";
//1. INIT FUNCTION
public PdfPageEventHandler function init(required any config) {
//make sure the config is accessable by other functions
variables.config = arguments.config;
return this;
}
//2. ON END PAGE - the function that is in focus in this example
public void function onEndPage(required any writer, required any document) {
//Called when a page is finished, just before being written to the document
//edit below to make your own header / footer
local.cb = arguments.writer.getDirectContent();
local.cb.saveState();
local.cb.beginText();
local.cb.setColorFill(variables.config.myCustomFooter.color);
local.cb.setFontAndSize(variables.config.myCustomFooter.font, variables.config.myCustomFooter.size);
local.cb.setTextMatrix(arguments.document.left(), arguments.document.bottom() - 10);
local.text = "#variables.config.myCustomFooter.text# #arguments.writer.getPageNumber()#";
local.cb.showText(local.text);
local.cb.endText();
local.cb.restoreState();
}
//3. OTHER FUNCTIONS THAT MUST EXIST (at least in this example)
public void function onOpenDocument(required any writer, required any document) {
//Called when the document is opened
}
public void function onCloseDocument(required any writer, required any document) {
//Called when the document is closed
}
public void function onStartPage(required any writer, required any document) {
//Called when a page is initialized
}
public void function onParagraph(required any writer, required any document, required numeric paragraphPosition) {
//Called when a Paragraph is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
}
public void function onParagraphEnd(required any writer, required any document, required numeric paragraphPosition) {
//Called when a Paragraph is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
}
//4. FUNCTIONS THAT ONLY NEEDS TO EXIST IF YOU DO SOMETHING THAT TRIGGERS THEM
public void function OnChapter(required any writer, required any document, required numeric paragraphPosition, required any title) {
//Called when a Chapter is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
//title - Title of the chapter. Instance of com.lowagie.text.Paragraph
}
public void function onChapterEnd(required any writer, required any document, required numeric position) {
//Called when the end of a Chapter is reached
//position - The position of the end of the chapter. Value is a java float
}
public void function onGenericTag(required any writer, required any document, required any rect, required string text) {
//Called when a Chunk with a generic tag is written
//rect - The Rectangle containing the Chunk. Instance of com.lowagie.text.Rectangle
//text - The text of the tag
}
public void function onSection(required any writer, required any document, required numeric paragraphPosition, required numeric depth, required any title) {
//Called when a Section is written
//paragraphPosition - The position the section will be written to. Value is a java float
//depth - The number depth of the Section. Value is a java int
//title - Title of the section. Instance of com.lowagie.text.Paragraph
}
public void function onSectionEnd(required any writer, required any document, required numeric paragraphPosition, required numeric depth, required any title) {
//Called when the end of a Section is reached
//paragraphPosition - The position the section will be written to. Value is a java float
//depth - The number depth of the Section. Value is a java int
//title - Title of the section. Instance of com.lowagie.text.Paragraph
}
}
</cfscript>