iTextSharp PDF一次合并和添加页码

时间:2016-02-24 05:48:54

标签: vb.net pdf itextsharp

我使用此代码合并并向页面添加页码:

            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)

我怎样才能一次性完成?

关于我的情况的一些更多细节:我需要创建一个大文件,正常情况下代码运行了几天并抛出了内存异常,所以我将它拆分为较小的文档,它工作得很好,但页码是一切都错了,然后我来到这一部分。

2 个答案:

答案 0 :(得分:3)

要同时合并文档并在其上标记某些内容,您可以使用PdfCopy.PageStamp。样本ConcatenateStamp.cs(对应于“iText in Action - 2nd Edition”一书中的java样本ConcatenateStamp.java)演示了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);
        }   
    }   
}

(样本是在C#中,而不是VB,但它应该用来提供一个想法......)

答案 1 :(得分:2)

请注意,当你没有正确处理东西时,通常会触发带有iTextSharp的OOM,并不总是意味着你正在使用太大的文件。运行时会将“内存”从RAM迁移到磁盘,这会减慢速度,但不应该崩溃(除非你的磁盘空间不足)。

对于您的第一个区块,我建议您尽可能使用using模式自动为您处理此问题。我没有通过VS运行此代码,因此它可能不是100%正确但应该非常准确。

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的解决方案向您展示如何在一个通道中执行此操作,这就是您要求的,我只是想确保您知道事情的时间和方式{/ 1}。