如何使用iText在每个页面上添加总页数?

时间:2009-04-17 10:29:59

标签: java itext

如何使用iText在每个页面上添加总页数?

11 个答案:

答案 0 :(得分:11)

  1. 首先使用虚拟页面数量处理从PdfWriterbytestream的输出。
  2. PdfReader创建bytestream,调用PdfReader.getNumberOfPages以获取实际的网页数。
  3. 重新创建PDF输出,知道页数是多少,相应地更改页脚。
  4. 这很麻烦,但没有简单的方法可以在没有两遍方法的情况下知道页数。有关操作PDF的详细信息,请参阅example code

答案 1 :(得分:7)

您可以创建一个继承自PdfPageEventHelper的类 然后覆盖这两个函数:

Imports System.Collections.Generic
Imports System.Text

Imports iTextSharp.text.pdf
Imports iTextSharp.text

Namespace PDF_EnteteEtPiedDePage
    Public Class EnteteEtPiedDePage
        Inherits PdfPageEventHelper
        ' This is the contentbyte object of the writer
        Private cb As PdfContentByte

        ' we will put the final number of pages in a template
        Private template As PdfTemplate

        ' this is the BaseFont we are going to use for the header / footer
        Private bf As BaseFont = Nothing

        ' This keeps track of the creation time
        Private PrintTime As DateTime = DateTime.Now

        ' we override the onOpenDocument method
        Public Overrides Sub OnOpenDocument(writer As PdfWriter, document As Document)
            Try
                PrintTime = DateTime.Now
                bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED)
                cb = writer.DirectContent
                template = cb.CreateTemplate(50, 50)
            Catch de As DocumentException
            Catch ioe As System.IO.IOException
            End Try
        End Sub

        Public Overrides Sub OnStartPage(writer As PdfWriter, document As Document)
            MyBase.OnStartPage(writer, document)

            Dim pageSize As Rectangle = document.PageSize

        End Sub

        Public Overrides Sub OnEndPage(writer As PdfWriter, document As Document)
            MyBase.OnEndPage(writer, document)

            Dim pageN As Integer = writer.PageNumber
            Dim text As [String] = "Page " & pageN & " de "
            Dim len As Single = bf.GetWidthPoint(text, 8)

            Dim pageSize As Rectangle = document.PageSize

            cb.SetRGBColorFill(100, 100, 100)

            cb.BeginText()
            cb.SetFontAndSize(bf, 8)
            cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30))
            cb.ShowText(text)
            cb.EndText()

            cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30))

            cb.BeginText()
            cb.SetFontAndSize(bf, 8)
            cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, "Imprimé le : " & PrintTime.ToShortDateString() & " à " & PrintTime.ToShortTimeString, pageSize.GetRight(40), pageSize.GetBottom(30), 0)
            cb.EndText()
        End Sub

        Public Overrides Sub OnCloseDocument(writer As PdfWriter, document As Document)
            MyBase.OnCloseDocument(writer, document)

            template.BeginText()
            template.SetFontAndSize(bf, 8)
            template.SetTextMatrix(0, 0)
            template.ShowText("" & Convert.ToString((writer.PageNumber - 1)))
            template.EndText()
        End Sub

    End Class
End Namespace

然后在此之后设置pdfwriter PageEvent的值如下:

Dim PageEventHandler = New EnteteEtPiedDePage()
            aPdfWriter.PageEvent = PageEventHandler

答案 2 :(得分:5)

不再搜索,这是解决方案。如果他们删除此链接,我会将代码发布到我的网站并托管链接。

iText page numbers example

答案 3 :(得分:3)

这是我使用的代码。将页面写入输出不会增加太多开销。

outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
contentByte = writer.getDirectContent();
....add stuff
document.close();
writer.close();
byte[] output = outputStream.toByteArray();
PdfReader reader = new PdfReader(output);
//reset the output
outputStream = new ByteArrayOutputStream();
output = new DataOutputStream(outputStream);
document = new Document();
writer = PdfWriter.getInstance(document, output);
document.open();
PdfStamper stamper = new PdfStamper(reader, outputStream);
//add the pages
for (int i = 1; i <= pageCount; i++)
{
    contentByte = stamper.getOverContent(i);
    addParagraph("Page " + i + " of " + pageCount, new Point(500, 30), boldTextFont);  // my own paragraph font
}
stamper.close();

答案 4 :(得分:2)

通过快速网络搜索提醒自己这一点;看看

Example

一旦你点击文档的末尾,相关的方法是onEndPage()产生“X”和onCloseDocument()以产生“Y”。

答案 5 :(得分:1)

这是一个方便的功能! (基于Milhous的方法)(这使用itext版本4.1.6.0)

public static byte[] AddPageNumbers(byte[] pdf)
        {
            PdfReader reader = new PdfReader(pdf);
            var Pages = reader.NumberOfPages;
            MemoryStream ms = new MemoryStream();

            PdfStamper stamper = new PdfStamper(reader, ms);
            for (int i = 1; i <= Pages; i++)
            {
                PdfContentByte overContent;
                Font Signature = FontFactory.GetFont("Calibiri", 9, iTextSharp.text.Font.NORMAL, Color.BLACK);
                overContent = stamper.GetOverContent(i);
                var helv = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
                overContent.SaveState();
                overContent.BeginText();
                overContent.SetFontAndSize(helv, 10.0f);
                overContent.SetTextMatrix(PageSize.LETTER.Width / 2 - 20, PageSize.LETTER.Height - (PageSize.LETTER.Height - 20));
                overContent.ShowText("Page " + (i) + " of " + Pages);
                overContent.EndText();
                overContent.RestoreState();
            }
            stamper.Close();            
            return ms.ToArray();
        }

答案 6 :(得分:0)

试试这个,因为我也受此影响而且我也新推了这个库所以经过很多麻烦我得到的结果只是尝试应用逻辑两次,就像我在评论中提到的那样。

class PdfReportServlet extends HttpServlet
{
    public static int total = 0;

    public static int getTotal() 
    {
        return total;
    }

    public static void setTotal(int total) {
        PdfReportServlet .total = total;
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    {
        String reportFor = request.getParameter("report");
        if(!"".equals(reportFor))
        {
            if(reportFor.equals("pdf"))
            {
    /* 
       from here logic starts
    */
                response.setContentType("application/pdf");
                Document document = new Document(PageSize.LETTER.rotate());
                try
                {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    PdfWriter pdfWriter = PdfWriter.getInstance(document, bos);
                    PdfReport pdfReport = new PdfReport();
                    pdfWriter.setPageEvent(pdfReport);
                    document.open();
                    String id = request.getParameter("id");
                    DettagliFamigliaPDFReport.generatePDFReport(document,id);
                    document.close();

                    /*
                     * now again give new references to Document and PdfWriter classes.
                     */

                    document = new Document(PageSize.LETTER.rotate());

                    pdfWriter = PdfWriter.getInstance(document, response.getOutputStream());
                    PDFReport.setTotalPages(getTotal());/*##PAGES_TOTAL here i set total Pages which i get from above logic */
                    PdfReport pdfReport = new PdfReport();
                    pdfWriter.setPageEvent(pdfReport);
                    document.open();
                    id = request.getParameter("id");
                    PDFReport.generatePDFReport(document,id);
                    document.close();

                }
                catch(DocumentException de){
                    de.printStackTrace();
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


}


/*
    Here below i write the class inherits the PdfPageEventHelper class and also having generatePDFReport() method.
*/


public class PDFReport extends PdfPageEventHelper
{
    public static PdfTemplate template;
    public static int totalPages=0;

    public static int getTotalPages() {
        return totalPages;
    }

    public static void setTotalPages(int totalPages) {
        DettagliFamigliaPDFReport.totalPages = totalPages;
    }


    public static void generatePDFReport(Document document,String id)
    {
        // here your data to write on page of pdf.
    }

    @Override
    public void onOpenDocument(PdfWriter writer, Document doc) 
    {
        template = writer.getDirectContent().createTemplate(100, 100);
    }

    int totalPage = 0;
    @Override
    public void onCloseDocument(PdfWriter writer, Document doc) 
    {
        totalPage = writer.getPageNumber() - 1;/* at the end this method calls and you will get total number of pages.*/
        PdfReportServlet.setTotal(totalPage); /* while first time logic of servlet executes then i set the total pages to servlet's variable using this logic.
and second time servlet's logic is executing i passed totalPages to this class variable
where i marked ##PAGES_TOTAL  */
    }

    @Override
    public void onStartPage(PdfWriter writer, Document doc) {
        // Here i write header logic when each time page starts.
    }

    @Override`enter code here`
    public void onEndPage(PdfWriter writer, Document doc) 
    {
        Rectangle rect = writer.getPageSize();
        float width = rect.getWidth()/2;   

        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        Date date = new Date();

        String footerOne = "This document is printed on date "+dateFormat.format(date)+" - Page. "+writer.getPageNumber()+" of "+getTotalPages();

        Paragraph paraOne = new Paragraph(footerOne);

        Font fontFooter = new Font();
        fontFooter.setSize(8);
        fontFooter.setColor(Color.gray);

        paraOne.setFont(fontFooter);

        Phrase footerPhraseOne = new Phrase(paraOne);
        ColumnText.showTextAligned(writer.getDirectContent(),
                Element.ALIGN_CENTER, footerPhraseOne,
                width, 30, 0);
    }
}

答案 7 :(得分:0)

这是您的代码片段:

final PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setPageEvent(new PageStamper());

编号代码:

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.*;
import com.itextpdf.tool.xml.css.*;

import java.io.IOException;

/**
 * Adds page number to al the pages except the first.
 */
public class PageStamper extends PdfPageEventHelper {
    private static final Logger logger = Logger.getLogger(PageStamper.class);

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        final int currentPageNumber = writer.getCurrentPageNumber();

        if (currentPageNumber == 1) {
            return;
        }

        try {
            final Rectangle pageSize = document.getPageSize();
            final PdfContentByte directContent = writer.getDirectContent();

            directContent.setColorFill(BaseColor.GRAY);
            directContent.setFontAndSize(BaseFont.createFont(), 10);

            directContent.setTextMatrix(pageSize.getRight(40), pageSize.getBottom(30));
            directContent.showText(String.valueOf(currentPageNumber));

        } catch (DocumentException | IOException e) {
            logger.error("PDF generation error", e);
        }
    }
}

此代码在此处找到:http://blog.abelsky.com/2014/01/22/adding-page-number-to-itext-generated-pdf/。非常感谢,andy722

答案 8 :(得分:0)

正如其他答案所示,您首先需要创建pdf,然后查看您创建的pdf包含的页数,然后将页脚添加到每个页面。 执行此操作的理想类是PdfStamper,其目的是向现有pdf /现有pdf页面添加其他元素。

以下是基于Milhous示例的详细示例:

Font smallFont = FontFactory.getFont("Arial", 9, Font.NORMAL);
ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
Document document = new Document(PageSize.A4, 70, 70, 40, 40);
PdfWriter pdfWriter = PdfWriter.getInstance(document, pdfOutputStream);

document.open();
//CREATE PDF HERE - ADD CONTENT TO DOCUMENT
document.close();

int pageCount = pdfWriter.getPageNumber()-1;
byte[] pdfAsBytes = pdfOutputStream.toByteArray();

//add footer
PdfReader reader = new PdfReader(pdfAsBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(outputStream);
document = new Document();
document.open();
PdfStamper stamper = new PdfStamper(reader, output);
for (int i = 1; i <= pageCount; i++) {
  ColumnText.showTextAligned(stamper.getOverContent(i), 
    Element.ALIGN_CENTER, new Phrase(i+"/" + pageCount, smallFont), 550, 30, 0);
}
stamper.close();
byte[] finalPdfAsBytes = outputStream.toByteArray();

答案 9 :(得分:0)

这是用Java编译的Rama代码(至少是其中的一部分)

public class test extends PdfPageEventHelper{
    private int _pg = 0;
    private BaseFont font;

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        _pg++;
        PdfContentByte cb = writer.getDirectContent();
        cb.beginText();
        try {
            Rectangle pageSize = document.getPageSize();
            cb.setFontAndSize(font, 8);
            cb.setTextMatrix(pageSize.getLeft(40), pageSize.getBottom(15));
            String s = "Page " + _pg + "/";
            cb.showText(s);
            cb.addTemplate(template, pageSize.getLeft(40) + font.getWidthPoint(s, 8), pageSize.getBottom(15));
        } catch (Exception exc) {
            logger.warn("got Exception : " + exc.getMessage());
        }
        cb.endText();
    }

    @Override
    public void onOpenDocument(PdfWriter writer, Document document) {
        super.onOpenDocument(writer, document);
        template = writer.getDirectContent().createTemplate(50, 50);
        try {
            font = BaseFont.createFont(BaseFont.COURIER, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
        } catch (Exception exc) {
            logger.warn("got Exception : " + exc.getMessage());
        }
    }

    @Override
    public void onCloseDocument(PdfWriter writer, Document document) {
        super.onCloseDocument(writer, document);

        template.beginText();
        try {
            template.setFontAndSize(font, 8);
            template.setTextMatrix(0f, 0f);
            template.showText("" + (writer.getPageNumber() - 1));
        } catch (Exception ex) {
            logger.error(ex);
        }
        template.endText();
    }

}

答案 10 :(得分:0)

经过两天的努力!我终于得到了PDF中的总页数。 实际上,我的客户要求是仅在PDF的最后一页上显示页脚。 我就是这样做的,希望以后能对某人有所帮助。 步骤1: 像这样创建新的类,该类将从 PdfPageEventHelper 继承。

public class ITextEvents : PdfPageEventHelper
{
public int pageNos { get; set; }

/// <summary>
/// CALLED ON EACH PAGE END PAGE, 
/// </summary>
/// <param name="writer"></param>
/// <param name="document"></param>
public override void OnEndPage(iTextSharp.text.pdf.PdfWriter writer, iTextSharp.text.Document document)
{
//LOGIC: TO SHOW DISCLAIMER ONLY ON LAST PAGE
if (document.PageNumber == pageNos)
{
//Create new Paragraph
Paragraph p = new Paragraph();
//ADD CHUNK IN PARAGRAPH
p.Add(new Chunk("Heading-Text: ", FontFactory.GetFont("Calibri",11,Font.BOLD)));
p.Add(new Chunk("Details sow in footer", FontFactory.GetFont("Calibri", 10)));
//PARAGRAPH TEXT ALIGNMENT. 
p.Alignment = Element.ALIGN_LEFT;
//CREATE PDF TABLE, FOR ADDING NEW CELL AND ROW IN THE PDF
PdfPTable footerTbl = new PdfPTable(1);
//SETING TABLE WIDTH
footerTbl.TotalWidth = 580;
footerTbl.HorizontalAlignment = Element.ALIGN_LEFT;
//ADDING CELL IN THE TABLE
PdfPCell cell = new PdfPCell(p);
//CELL LAYOUT DESIGN
cell.Border = 1;
cell.PaddingLeft = 10;
cell.PaddingRight = 10;
footerTbl.AddCell(cell);
//ADDING TABLE IN THE PDF
footerTbl.WriteSelectedRows(0, -1, 10, 110, writer.DirectContent);
}
}

/// <summary>
/// THIS METHOD WILL GET TOTAL PDF PAGES COUNT,
/// REQUIREMENT OF THIS METHOD WAS IS TO SHOW FOOTER ON LAST PAGE IN THE PDF. 
/// </summary>
/// <param name="HistoryHTML"></param>
/// <param name="Name"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public int GetTotalPageCount(string HistoryHTML, String Name, string filePath)
{
try
{
using (MemoryStream stream = new System.IO.MemoryStream())
{
StringReader sr = new StringReader(HistoryHTML);
Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 30f, 90f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
pdfDoc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
pdfDoc.Close();

bool exists = System.IO.Directory.Exists(filePath);
if (!exists)
    System.IO.Directory.CreateDirectory(filePath);
System.IO.File.WriteAllBytes((filePath + @"\FileName-" + Name + ".pdf"), stream.ToArray());

string path = AppDomain.CurrentDomain.BaseDirectory + @"FolderPath\" + "FileName-" + Name + ".pdf";

PdfReader pdfReader = new PdfReader(path);
int numberOfPages = pdfReader.NumberOfPages;
pdfReader.Close();
stream.Close();
return numberOfPages;

}
}
catch (Exception ex)
{
CommonFunction.logElmahError(ex);
}
return -1;
}
}  

在从流中生成pdf文件之前,请调用此方法以获取总页数。

int pageCount = new Common.ITextEvents().GetTotalPageCount(HistoryHTML, Name, Server.MapPath("~/FolderPath"));

为了更好地理解,我提供了控制器端代码。

public string ExportPDF(string HistoryHTML, String Name)
        {
            int pageCount = new Common.ITextEvents().GetTotalPageCount(HistoryHTML, Name, Server.MapPath("~/FolderPath"));

            using (MemoryStream stream = new System.IO.MemoryStream())
            {
                StringReader sr = new StringReader(HistoryHTML);
                Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 30f, 30f);
                PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
                pdfDoc.Open();

                //APPEND DISCLAIMER TEXT ACCORING TO HIPAA RULES.
                writer.PageEvent = new Common.ITextEvents() { pageNo = pageCount };

                XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
                pdfDoc.Close();

                bool exists = System.IO.Directory.Exists(Server.MapPath("~/FolderPath"));
                if (!exists)
                    System.IO.Directory.CreateDirectory(Server.MapPath("~/FolderPath"));
                System.IO.File.WriteAllBytes(Server.MapPath("~/FolderPath/" + Name + ".pdf"), stream.ToArray());

                return File(stream.ToArray(), "application/pdf", "FileName-" + Name + "-" + Name + ".pdf");
            }
        }