iTextSharp PDF 一口气合并和添加页码
iTextSharp PDF Merging and adding page number in one go
我使用此代码合并文档并将页码添加到文档:
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)
如何一次完成?
关于我的情况的更多细节:我需要创建一个大文件,以正常方式代码 运行 几天并抛出内存不足异常,所以我将它拆分为较小的文件,它有效很好,但是页码都错了,那我就到这部分了。
要合并文档并同时在文档上标记内容,您可以使用 PdfCopy.PageStamp
。 "iText in Action - 2nd Edition" 书中的示例 ConcatenateStamp.cs (corresponding to the java sample 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 但它应该可以提供一个想法...)
请注意,当您没有正确处理东西时,通常会触发 iTextSharp 的 OOM,并不总是意味着您正在处理太大的文件。 运行时间会将 "memory" 从 RAM 转移到磁盘,这会减慢速度但不会崩溃(当然,除非你 运行 磁盘 space 不足) .
对于您的第一个块,我鼓励您尽可能使用 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 的解决方案向您展示了如何一次完成,这正是您所要求的,我只是想确保您知道什么时候以及如何 Dispose
事情。
我使用此代码合并文档并将页码添加到文档:
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)
如何一次完成?
关于我的情况的更多细节:我需要创建一个大文件,以正常方式代码 运行 几天并抛出内存不足异常,所以我将它拆分为较小的文件,它有效很好,但是页码都错了,那我就到这部分了。
要合并文档并同时在文档上标记内容,您可以使用 PdfCopy.PageStamp
。 "iText in Action - 2nd Edition" 书中的示例 ConcatenateStamp.cs (corresponding to the java sample 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 但它应该可以提供一个想法...)
请注意,当您没有正确处理东西时,通常会触发 iTextSharp 的 OOM,并不总是意味着您正在处理太大的文件。 运行时间会将 "memory" 从 RAM 转移到磁盘,这会减慢速度但不会崩溃(当然,除非你 运行 磁盘 space 不足) .
对于您的第一个块,我鼓励您尽可能使用 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 的解决方案向您展示了如何一次完成,这正是您所要求的,我只是想确保您知道什么时候以及如何 Dispose
事情。