2009-04-17 1 views

ответ

11
  1. Обработать вывод с PdfWriter до bytestream с использованием фиктивной страницы.
  2. Создайте PdfReader из этого bytestream, позвонив по номеру PdfReader.getNumberOfPages, чтобы получить фактическое количество страниц.
  3. Восстановите вывод в формате PDF, зная, что такое счетчик страниц, соответственно изменив нижний колонтитул.

Это грязный, но нет простого способа узнать количество страниц без двухпроходного подхода. Подробные сведения о работе с PDF-файлами см. В разделе example code.

+0

Согласен, это действительно уродливо, но это также единственный способ пойти с iText. Если кто-нибудь знает лучшую библиотеку Java PDF (желательно бесплатно/OSS), я бы с удовольствием узнал об этом. –

+0

Для использования PDF-ридера документ должен быть закрыт, иначе он не станет заголовком PDF. Поэтому, используя его в каждом нижнем колонтитуле, документ должен быть открыт для записи каждого нижнего колонтитула. –

3

Из быстрого поиска в Интернете, чтобы напомнить себе об этом; посмотрите на

Example

Соответствующие методы onEndPage() для получения «X» и onCloseDocument() для получения «Y», как только вы попали в конец документа.

+0

Кажется Предпочитаемый способ , Но есть проблема с вычисленной переменной «adjust»: она рассчитана для одного символа: «helv.getWidthPoint (« 0 », 12)». :-( – trunkc

+0

Пример ссылки не найден – understack

+0

Пример не доступен – Luixv

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(); 
+1

Ваш код не говорит, где он получил pageCount from. – user705142

+1

Вы считаете номер при добавлении страниц. – Milhous

+1

@Milhous не могли бы вы объяснить: addParagraph («Страница» + i + »из« + pageCount, новая точка (500 , 30), boldTextFont); // мой собственный шрифт абзаца Где это? – Pinch

5

Больше не искать, вот решение. Если они удалят эту ссылку, я отправлю код на свой сайт и разместим ссылку.

iText page numbers example

+0

на всякий случай: http://www.blackacedesign.com/pages/directory/itext-page-numbers-example.jsp –

6

Вы можете создать класс, который наследует от 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 
+1

Это не код Java, вопрос был помечен [java]. В любом случае, полезно. – ymajoros

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); 
    } 
} 
1

Это удобная функция! (На основе подхода Милхаус в) (это использует 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(); 
     } 
+0

Я преобразовал это в Java, и это не сработало для меня. :( –

+0

@pinch Как я могу назвать этот метод и где? – Euridice01

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

0

Как указывают другие ответы, сначала необходимо создать pdf-файл, а затем посмотреть, сколько страниц содержит файл pdf, а затем добавить нижний колонтитул на каждую страницу. Идеальный класс для этого - PdfStamper, целью которого является добавление дополнительных элементов в существующие pdf/существующие pdf-страницы.

Вот сложный пример, основанный на примере Милхаус:

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(); 
0

Это код Рама преобразуется в Java (часть его, по крайней мере)

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(); 
    } 

} 
+0

@Rama Если вы хотите, вы можете взять этот код, чтобы добавить его в свой ответ. Предотвратите, если вы это сделаете. – AxelH

Смежные вопросы