Reputation: 416
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.
Upvotes: 0
Views: 2627
Reputation: 55457
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.
Upvotes: 2
Reputation: 96039
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...)
Upvotes: 3