当前位置: 首页 > 知识库问答 >
问题:

使用Coldfusion和iText通过onEndPage向PDF添加页脚/页眉

卜勇
2023-03-14

我使用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);

(至少据我所知。)

<cfset local.PdfPageEventHelper=CreateObject("java","com.lowagie.text.pdf.PdfPageEventHelper")>

共有1个答案

许天逸
2023-03-14

这个解决方案主要基于cfsearching.blogspot.se的这篇旧博客文章。

虽然该解决方案使用javaloader动态代理库,但该解决方案使用较新的(?)函数CreateDynamicProxy(我想可以从ColdFusion 10中获得),它是Ageax(非常感谢!)让我意识到。

这已经在Linux服务器上的ColdFusion 11中成功地测试过了。

    null
<!---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>
<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>
 类似资料:
  • 使用iTextSharp,您可以通过将事件附加到PDF来向PDF添加页眉/页脚,如本SO答案中所述:https://stackoverflow.com/a/19004392 我怎样才能用 iText 7 做同样的事情? 这个链接有Java代码示例,但看起来不像它使用的页面事件。

  • 问题内容: 在我的pdf文件中,我需要有多个页眉和页脚。在页眉中,我希望标题标题位于左侧,而某些文本位于中心。 同样,在页脚中,我需要在左侧打印公司名称,在中心打印页码,并在右侧打印有关表格内容的一些信息。 我看过很多文章,但是我没有正确的想法来创建它,有人请帮助我提供一些示例代码片段。 问题答案: 页眉和页脚应使用“页面事件”添加。如果您需要一些示例,只需在官方网站上查找关键字header /

  • 问题内容: 我正在尝试使用具有以下代码的iText 7创建PDF文档,并且生成时,我的PDF文档内容在同一页面中重叠(即,在第1页中)。 我看到了 document.newPage(); iText 7中缺少该方法。如何在itext 7中不使用pdfDocumet.copyPages(…)或PDFmerger将页面添加到我的PDF文档中。 问题答案: 在iText 7中,该方法已成为区域中断的特殊

  • 问题内容: 如何在我的PDF页面中添加 页眉 和 页脚 ?我想要一个表,表头中有3列,其他表中,页脚中有3列。我的页面可能是A3或A4,并且是横向或纵向。 谁能帮我?我在互联网上找不到很好的例子。 谢谢! mas正 问题答案: 创建一个MyPageEventListener类,该类扩展了 PdfPageEventHelper 将页面事件侦听器添加到PdfWriter对象 在MyPageEventL