加快大型PDF的頁首和頁尾
This article was translated from English: Does it need improvement?
Translated
View the article in English
在一次處理中為非常大的PDF新增頁首和頁尾會很慢。 將文件按固定大小的頁面塊進行處理,渲染每個批次,然後將部分合併回來,以減少總渲染時間,同時保持整個文件的頁碼連續。
解決方案
1. 將頁面索引分批
選擇一個塊大小,將文件的頁面索引按固定大小分組,例如每批300頁。 較小的塊單獨渲染時更快,但會在最後增加更多的合併工作。
2. 將每個批次複製到自己的文件中
使用CopyPages提取當前批次的頁面,讓您得到一個獨立的文件進行渲染。
3. 使用連續編號渲染頁首和頁尾
將FirstPageNumber設置為塊的起始頁,這樣編號會覆蓋整個文件,而不是每個塊從1開始重新起算。
4. 保存每個塊並釋放
將每個塊寫入臨時文件並釋放。 在下一批開始之前釋放塊,防止記憶體在運行過程中不斷增加。
5. 將塊合併到最終PDF中
重新打開臨時文件,使用AppendPdf按順序追加它們,保存結果,然後刪除臨時文件。
using IronPdf;
var pdf = PdfDocument.FromFile("input.pdf");
string headerHtml = "<div style='font-size:10px;'>Header</div>";
string footerHtml = "<div style='text-align:right;font-size:10px;'>Page {page} of {total-pages}</div>";
int chunkSize = 300;
var pageChunks = Enumerable.Range(0, pdf.PageCount)
.GroupBy(i => i / chunkSize)
.Select(g => g.ToArray())
.ToList();
var tempFiles = new List<string>();
foreach (var indexes in pageChunks)
{
var chunkPdf = pdf.CopyPages(indexes);
int globalStartPage = indexes.First() + 1;
chunkPdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
FirstPageNumber = globalStartPage, // keeps numbering continuous
HtmlHeader = new HtmlHeaderFooter { HtmlFragment = headerHtml, MaxHeight = 40 },
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = footerHtml, MaxHeight = 40 }
});
string tempFile = Path.GetTempFileName() + ".pdf";
chunkPdf.SaveAs(tempFile);
chunkPdf.Dispose();
tempFiles.Add(tempFile);
}
// Merge the chunks back into one document.
var finalPdf = new PdfDocument(tempFiles.First());
foreach (var file in tempFiles.Skip(1))
{
using var part = new PdfDocument(file);
finalPdf.AppendPdf(part);
}
finalPdf.SaveAs("output.pdf");
finalPdf.Dispose();
// Clean up temp files.
foreach (var file in tempFiles)
File.Delete(file);
using IronPdf;
var pdf = PdfDocument.FromFile("input.pdf");
string headerHtml = "<div style='font-size:10px;'>Header</div>";
string footerHtml = "<div style='text-align:right;font-size:10px;'>Page {page} of {total-pages}</div>";
int chunkSize = 300;
var pageChunks = Enumerable.Range(0, pdf.PageCount)
.GroupBy(i => i / chunkSize)
.Select(g => g.ToArray())
.ToList();
var tempFiles = new List<string>();
foreach (var indexes in pageChunks)
{
var chunkPdf = pdf.CopyPages(indexes);
int globalStartPage = indexes.First() + 1;
chunkPdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
FirstPageNumber = globalStartPage, // keeps numbering continuous
HtmlHeader = new HtmlHeaderFooter { HtmlFragment = headerHtml, MaxHeight = 40 },
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = footerHtml, MaxHeight = 40 }
});
string tempFile = Path.GetTempFileName() + ".pdf";
chunkPdf.SaveAs(tempFile);
chunkPdf.Dispose();
tempFiles.Add(tempFile);
}
// Merge the chunks back into one document.
var finalPdf = new PdfDocument(tempFiles.First());
foreach (var file in tempFiles.Skip(1))
{
using var part = new PdfDocument(file);
finalPdf.AppendPdf(part);
}
finalPdf.SaveAs("output.pdf");
finalPdf.Dispose();
// Clean up temp files.
foreach (var file in tempFiles)
File.Delete(file);
Imports IronPdf
Imports System.IO
Imports System.Linq
Dim pdf = PdfDocument.FromFile("input.pdf")
Dim headerHtml As String = "<div style='font-size:10px;'>Header</div>"
Dim footerHtml As String = "<div style='text-align:right;font-size:10px;'>Page {page} of {total-pages}</div>"
Dim chunkSize As Integer = 300
Dim pageChunks = Enumerable.Range(0, pdf.PageCount) _
.GroupBy(Function(i) i \ chunkSize) _
.Select(Function(g) g.ToArray()) _
.ToList()
Dim tempFiles = New List(Of String)()
For Each indexes In pageChunks
Dim chunkPdf = pdf.CopyPages(indexes)
Dim globalStartPage As Integer = indexes.First() + 1
chunkPdf.AddHtmlHeadersAndFooters(New ChromePdfRenderOptions With {
.FirstPageNumber = globalStartPage,
.HtmlHeader = New HtmlHeaderFooter With {.HtmlFragment = headerHtml, .MaxHeight = 40},
.HtmlFooter = New HtmlHeaderFooter With {.HtmlFragment = footerHtml, .MaxHeight = 40}
})
Dim tempFile As String = Path.GetTempFileName() & ".pdf"
chunkPdf.SaveAs(tempFile)
chunkPdf.Dispose()
tempFiles.Add(tempFile)
Next
' Merge the chunks back into one document.
Dim finalPdf = New PdfDocument(tempFiles.First())
For Each file In tempFiles.Skip(1)
Using part = New PdfDocument(file)
finalPdf.AppendPdf(part)
End Using
Next
finalPdf.SaveAs("output.pdf")
finalPdf.Dispose()
' Clean up temp files.
For Each file In tempFiles
File.Delete(file)
Next
$vbLabelText
$csharpLabel
Page {page} of {total-pages}這樣的頁腳從第一個塊到最後一個塊保持一致。
請注意如果沒有FirstPageNumber,每個塊的編號都會從第1頁重新開始。
除錯提示
- 調整塊大小:上面的值(300)是可調的,開始分塊產生效益的點取決於您的工作量。
- 考慮合併步驟:總時間是每塊渲染加上最後合併,因此在任何比較中都要考慮這一額外步驟。
- 在非常大的工作中控制記憶體:在合併過程中定期強制進行垃圾回收並使用
MaxDynamicHFPagesPerBatch調整瀏覽器池可以有所幫助。
準備開始了嗎?
Nuget 下載 20,296,129 | 版本: 2026.7 剛剛發布

