iTextSharp PDF Merging and adding page number in one go

北战南征 提交于 2019-12-25 07:53:24

问题


I use this code to merge and add page number to the document:

            Using stream As FileStream = New FileStream(targetPDF, FileMode.Create)
            Dim myDoc As Document
            If (ExportOption.Orientation = Global.GenerateReport.GenerateReport.Orientation.Portrait) Then
                myDoc = New Document(New iTextSharp.text.Rectangle(PAGE_WIDTH, PAGE_HEIGHT), MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM)
                myDoc.SetPageSize(PageSize.A4)
            Else
                myDoc = New Document(New iTextSharp.text.Rectangle(PAGE_WIDTH, PAGE_HEIGHT), MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM)
                myDoc.SetPageSize(PageSize.A4.Rotate())
            End If
            Dim pdfCopy As PdfCopy = New PdfCopy(myDoc, stream)
            myDoc.Open()

            Dim files() As String = Directory.GetFiles(sourceDir)
            For Each pdffile As String In files
                Dim reader As PdfReader = New PdfReader(pdffile)
                pdfCopy.AddDocument(reader)
                reader.Close()
            Next

            If (Not myDoc Is Nothing) Then
                myDoc.Close()
                pdfCopy.Close()
            End If
        End Using

        Dim bytes As Byte() = File.ReadAllBytes(targetPDF)
        Dim blackFont As iTextSharp.text.Font = FontFactory.GetFont("HELVETICA", 8, iTextSharp.text.Font.NORMAL, BaseColor.BLACK)
        Using stream As New MemoryStream()
            Dim reader As New PdfReader(bytes)
            Using stamper As New PdfStamper(reader, stream)

                Dim bottom As Single = 10.0F
                Dim left As Single = 550.0F

                Dim pages As Integer = reader.NumberOfPages
                For i As Integer = 1 To pages
                    ColumnText.ShowTextAligned(stamper.GetUnderContent(i), Element.ALIGN_RIGHT, New Phrase("Page " & i.ToString() & " of " & reader.NumberOfPages, blackFont), left, bottom, 0)
                Next
            End Using
            bytes = stream.ToArray()
        End Using
        File.WriteAllBytes(targetPDF, bytes)

How can I do it in just one go?

Some more details about my situation: I need to create a big file, in normal way the code ran for several days and threw Out of memory exception, so I split it to smaller documents, it works great but the page number is all wrong, then I come to this part.


回答1:


To merge documents and stamp something on them at the same time, you can use a PdfCopy.PageStamp. The sample ConcatenateStamp.cs (corresponding to the java sample ConcatenateStamp.java from the book "iText in Action - 2nd Edition") demonstrates the use of a PdfCopy.PageStamp:

using (Document document = new Document()) {
    using (PdfCopy copy = new PdfCopy(document, OUTPUT_STREAM)) {
        document.Open();
        // reader for document 1
        PdfReader reader1 = new PdfReader(r1);
        int n1 = reader1.NumberOfPages;
        // reader for document 2
        PdfReader reader2 = new PdfReader(r2);
        int n2 = reader2.NumberOfPages;
        // initializations
        PdfImportedPage page;
        PdfCopy.PageStamp stamp;
        // Loop over the pages of document 1
        for (int i = 0; i < n1; ) {
            page = copy.GetImportedPage(reader1, ++i);
            stamp = copy.CreatePageStamp(page);
            // add page numbers
            ColumnText.ShowTextAligned(
              stamp.GetUnderContent(), Element.ALIGN_CENTER,
              new Phrase(string.Format("page {0} of {1}", i, n1 + n2)),
              297.5f, 28, 0
            );
            stamp.AlterContents();
            copy.AddPage(page);
        }

        // Loop over the pages of document 2
        for (int i = 0; i < n2; ) {
            page = copy.GetImportedPage(reader2, ++i);
            stamp = copy.CreatePageStamp(page);
            // add page numbers
            ColumnText.ShowTextAligned(
              stamp.GetUnderContent(), Element.ALIGN_CENTER,
              new Phrase(string.Format("page {0} of {1}", n1 + i, n1 + n2)),
              297.5f, 28, 0
            );
            stamp.AlterContents();
            copy.AddPage(page);
        }   
    }   
}

(The sample is in C#, not VB but it should serve to give an idea...)




回答2:


Just a note, an OOM with iTextSharp is usually triggered when you aren't properly disposing things and doesn't always means that you're working with files that are too large. The runtime will swamp "memory" from RAM to disk for you which will slow things down but shouldn't crash anything (unless you run out of disk space of course).

For your first block I'd encourage you to use the using pattern as much as possible to handle this for you automatically. I didn't run this code through VS so it might not be 100% correct but should be pretty much accurate.

Using stream As New FileStream(targetPDF, FileMode.Create)
    Using myDoc As New Document(New iTextSharp.text.Rectangle(PAGE_WIDTH, PAGE_HEIGHT), MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM)

        If (ExportOption.Orientation = Global.GenerateReport.GenerateReport.Orientation.Portrait) Then
            myDoc.SetPageSize(PageSize.A4)
        Else
            myDoc.SetPageSize(PageSize.A4.Rotate())
        End If

        Using pdfCopy New PdfCopy(myDoc, stream)

            myDoc.Open()

            Dim files() As String = Directory.GetFiles(sourceDir)
            For Each pdffile As String In files
                Using reader As PdfReader = New PdfReader(pdffile)
                    pdfCopy.AddDocument(reader)
                End Using
            Next

            myDoc.Close()

        End Using
    End Using
End Using

@mkl's solution shows you how to do it in one pass which is what you asked for, I just wanted to make sure that you knew when and how Dispose of things.



来源:https://stackoverflow.com/questions/35594251/itextsharp-pdf-merging-and-adding-page-number-in-one-go

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!