大規模PDFでのヘッダーとフッターの高速化
非常に大きな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);
Page {page} of {total-pages}のようなフッターが最初のチャンクから最後まで一貫します。
デバッグのヒント
- チャンクサイズを調整: 上記の値(300)は調整可能で、チャンク化が有効になるポイントはワークロードに依存します。
- マージパスを考慮してください: 合計時間はチャンクごとのレンダリングに加えて最終マージですので、その追加のパスを比較に含めてください。
- 非常に大きなジョブではメモリを抑える: マージ中に定期的にガベージコレクションを強制し、
MaxDynamicHFPagesPerBatchでブラウザプールを調整することが役立ちます。

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.