Headers e Rodapés Mais Rápidos em PDFs Grandes
Adicionar cabeçalhos e rodapés a um PDF muito grande em uma única passagem é lento. Processar o documento em pedaços de páginas de tamanho fixo, renderizar cada lote e depois mesclar as partes novamente para reduzir o tempo total de renderização enquanto mantém a numeração das páginas contínua em todo o documento.
Solução
1. Divida os índices de página em lotes
Escolha um tamanho de pedaço e agrupe os índices de páginas do documento em lotes de tamanho fixo, por exemplo, 300 páginas cada. Pedaços menores são renderizados mais rapidamente individualmente, mas adicionam mais trabalho de mesclagem no final.
2. Copie cada lote em seu próprio documento
Extraia as páginas para o lote atual com CopyPages, fornecendo um documento independente para renderizar.
3. Renderize cabeçalhos e rodapés com numeração contínua
Defina FirstPageNumber para a página inicial do pedaço, para que a numeração cubra o documento inteiro em vez de reiniciar no 1 em cada pedaço.
4. Salve cada pedaço e descarte-o
Escreva cada pedaço em um arquivo temporário e descarte-o. Liberar o pedaço antes do próximo lote impede que a memória aumente durante a execução.
5. Mescle os pedaços no PDF final
Reabra os arquivos temporários, anexe-os em ordem com AppendPdf, salve o resultado e, em seguida, exclua os arquivos temporários.
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);
FirstPageNumber é a chave: ele é configurado para a página inicial global de cada pedaço, de modo que um rodapé como Page {page} of {total-pages} fique consistente do primeiro ao último pedaço.
Dicas de Depuração
- Ajuste o tamanho do pedaço: o valor acima (300) é ajustável, e o ponto em que a divisão começa a compensar depende da sua carga de trabalho.
- Considere a passagem de mesclagem: o tempo total é a renderização por pedaço mais a mesclagem final, então considere essa passagem extra em qualquer comparação.
- Mantenha a memória sob controle em trabalhos muito grandes: forçar a coleta de lixo periodicamente durante a mesclagem e ajustar o pool do navegador com
BrowserPool.MaxIdleTabseMaxDynamicHFPagesPerBatchpode ajudar.

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.