Como escolher uma biblioteca de geração de documentos for .NET 8
.NET 8 introduziu mudanças de runtime que quebram a compatibilidade com muitas bibliotecas PDF tradicionais. System.Drawing.Common está obsoleto em plataformas que não são Windows, AOT Nativo impõe novas restrições em bibliotecas pesadas de reflexão, e o modelo de implantação de container expõe problemas de dependência que não surgiram em máquinas de desenvolvimento Windows. Bibliotecas que funcionavam no .NET Framework ou mesmo no .NET 6 podem falhar com erros NU1202, DllNotFoundException, ou PlatformNotSupportedException no .NET 8.
Este artigo documenta quais bibliotecas PDF funcionam com .NET 8, mostra os erros específicos que você encontrará com bibliotecas incompatíveis e fornece configurações de implantação para Docker e Azure Functions.
Início Rápido: Gerar PDF a partir de HTML no .NET 8
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<head><style>
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #2563eb; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style></head>
<body>
<h1>Q4 Report</h1>
<table>
<tr><th>Metric</th><th>Value</th><th>Change</th></tr>
<tr><td>Revenue</td><td>$1.2M</td><td>+12%</td></tr>
<tr><td>Users</td><td>45,230</td><td>+23%</td></tr>
</table>
</body></html>");
pdf.SaveAs("report.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<head><style>
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #2563eb; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style></head>
<body>
<h1>Q4 Report</h1>
<table>
<tr><th>Metric</th><th>Value</th><th>Change</th></tr>
<tr><td>Revenue</td><td>$1.2M</td><td>+12%</td></tr>
<tr><td>Users</td><td>45,230</td><td>+23%</td></tr>
</table>
</body></html>");
pdf.SaveAs("report.pdf");
Instale via NuGet: Install-Package IronPdf. Destina-se a net8.0 sem configurações adicionais. Desdobra-se para Windows, Linux, macOS, Docker, e Azure sem configuração específica da plataforma.
Por Que Bibliotecas PDF Antigas Falham no .NET 8?
iTextSharp — Não Compatível com .NET 8
iTextSharp (a porta original for .NET do iText) não é atualizado desde 2018. Ele visa apenas o .NET Framework:
erro NU1202: Pacote iTextSharp 5.5.13 não é compatível com net8.0
O caminho de migração é iText 7, que tem uma API diferente e requer conformidade com AGPL (tornar sua aplicação inteira open-source) ou licenciamento comercial. Preços não são publicados — dados de terceiros sugerem $15,000–$210,000/ano.
Envoltórios wkhtmltopdf — Falhas de Carregamento de DLL no .NET 8
Envoltórios C# em torno de wkhtmltopdf (DinkToPdf, Rotativa, NReco.PdfGenerator) falham com erros específicos de plataforma que são exclusivos do modelo de implantação do .NET 8:
DinkToPdf — biblioteca nativa não encontrada:
System.DllNotFoundException: Não foi possível carregar a DLL 'libwkhtmltox'
Rotativa.AspNetCore — requer configuração manual do caminho binário que conflita com a implantação container-first do .NET 8:
// This pattern requires deploying wkhtmltopdf binaries alongside your app
// and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf");
// This pattern requires deploying wkhtmltopdf binaries alongside your app
// and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf");
TuesPechkin / NReco — incompatibilidade de arquitetura:
System.BadImageFormatException: Não foi possível carregar o arquivo ou assembly
Esses erros refletem um problema mais profundo: wkhtmltopdf foi arquivado em julho de 2024 com CVEs não corrigidos. A arquitetura binária nativa é anterior às melhorias de detecção de plataforma do .NET 8. Não há correção — apenas migração para uma biblioteca diferente.
PdfSharp— Falhas do System.Drawing.Common no Linux
PdfSharp depende do System.Drawing.Common, que a Microsoft descontinuou para plataformas não Windows no .NET 6. No .NET 8, isso gera falhas em tempo de execução ao implantar no Linux ou Docker:
using PdfSharp.Pdf;
using PdfSharp.Drawing;
var document = new PdfDocument();
// PlatformNotSupportedException on Linux:
// System.Drawing.Common is not supported on this platform
using PdfSharp.Pdf;
using PdfSharp.Drawing;
var document = new PdfDocument();
// PlatformNotSupportedException on Linux:
// System.Drawing.Common is not supported on this platform
Desde o início de 2026,PdfSharp6.x tem trabalhado para remover essa dependência, mas o suporte multiplataforma permanece incompleto. Para implantações somente no Windows,PdfSharpfunciona com .NET 8. Para Linux, Docker ou implantações na nuvem, é pouco confiável.
Quais bibliotecas PDF funcionam com o .NET 8?
IronPDF— Suporte completo ao .NET 8, multiplataforma
IronPDF visa net8.0 nativamente com renderização Chromium embutida. Sem dependência do System.Drawing.Common, sem gerenciamento de binários nativos, sem configuração específica de plataforma.
Integração mínima de API (o padrão principal do .NET 8):
using IronPdf;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/invoice/{id}/pdf", async (int id, InvoiceService service) =>
{
var invoice = await service.GetInvoiceAsync(id);
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml());
return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf");
});
app.Run();
using IronPdf;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/invoice/{id}/pdf", async (int id, InvoiceService service) =>
{
var invoice = await service.GetInvoiceAsync(id);
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml());
return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf");
});
app.Run();
Para equipes utilizando o padrão de controlador, o mesmo código funciona dentro de uma ação do controlador — RenderHtmlAsPdf retorna um PdfDocument que você pode converter para bytes com .BinaryData.
Licenciamento: Licença perpétua a partir de US$ 749 (Lite — 1 desenvolvedor, 1 projeto). Professional: US$ 1.499 (10 desenvolvedores). Enterprise: US$ 2.999 (ilimitado). Publicado em ironpdf.com.
QuestPDF— Compatível com .NET 8, Sem HTML
QuestPDF funciona com .NET 8 sem dependências de plataforma. Sua API fluente em C# cria documentos programaticamente — sem parser HTML, sem mecanismo de CSS, sem mecanismo de navegador:
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
QuestPDF.Settings.License = LicenseType.Community; // Free under $1M revenue
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(col =>
{
col.Item().Text("Q4 Report").FontSize(24).Bold();
col.Item().Table(table =>
{
table.ColumnsDefinition(c => { c.RelativeColumn(2); c.RelativeColumn(1); c.RelativeColumn(1); });
table.Header(h =>
{
h.Cell().Text("Metric").Bold();
h.Cell().Text("Value").Bold();
h.Cell().Text("Change").Bold();
});
table.Cell().Text("Revenue"); table.Cell().Text("$1.2M"); table.Cell().Text("+12%");
table.Cell().Text("Users"); table.Cell().Text("45,230"); table.Cell().Text("+23%");
});
});
});
}).GeneratePdf("report.pdf");
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
QuestPDF.Settings.License = LicenseType.Community; // Free under $1M revenue
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(col =>
{
col.Item().Text("Q4 Report").FontSize(24).Bold();
col.Item().Table(table =>
{
table.ColumnsDefinition(c => { c.RelativeColumn(2); c.RelativeColumn(1); c.RelativeColumn(1); });
table.Header(h =>
{
h.Cell().Text("Metric").Bold();
h.Cell().Text("Value").Bold();
h.Cell().Text("Change").Bold();
});
table.Cell().Text("Revenue"); table.Cell().Text("$1.2M"); table.Cell().Text("+12%");
table.Cell().Text("Users"); table.Cell().Text("45,230"); table.Cell().Text("+23%");
});
});
});
}).GeneratePdf("report.pdf");
QuestPDF não converte HTML. Se o seu fluxo de trabalho usa modelos HTML (visualizações Razor, exportações de painel, arquivamento de conteúdo da web), você precisa de uma biblioteca diferente. A Licença Comunitária cobre negócios com receita anual inferior a US$ 1 milhão; acima disso, é necessário licenciamento comercial.
iText 7— Compatível com .NET 8, Licenciado AGPL
iText 7 (o sucessor do iTextSharp) suporta .NET 8. O complemento pdfHTML fornece conversão de HTML para PDF com um parser personalizado — não um mecanismo de navegador, então recursos modernos de CSS (Flexbox, Grid) não são renderizados corretamente.
Licenciamento: AGPL para uso open source, licenciamento comercial (assinatura, preços não publicados) para aplicativos proprietários. O iText mudou para licenciamento comercial baseado em assinatura em 2024.
Implantação do Docker
Imagem padrão do Debian (Recomendado)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
#IronPDFworks without additional apt-get installs
# Chromium dependencies are handled internally
COPY --from=build /app/publish .
ENV DOTNET_RUNNING_IN_CONTAINER=true
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]
Imagem Alpine (Pegada menor)
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
WORKDIR /app
# Alpine requires explicit Chromium dependencies
RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
A imagem do Debian não requer pacotes adicionais. A imagem Alpine é menor mas necessita da instalação explícita da biblioteca Chromium. Para a maioria das implantações, a imagem padrão do Debian é mais simples e confiável.
Funções do Azure (Trabalhador Isolado)
As funções do .NET 8 no Azure usam o modelo de trabalhador isolado.IronPDFfunciona com este modelo para geração de PDF sob demanda:
using IronPdf;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace MyApp.Functions;
public class PdfFunctions
{
[Function("GenerateInvoice")]
public async Task<HttpResponseData> GenerateInvoice(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
var invoice = await req.ReadFromJsonAsync<InvoiceRequest>();
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice));
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
response.Headers.Add("Content-Disposition",
$"attachment; filename=invoice-{invoice.Id}.pdf");
await response.Body.WriteAsync(pdf.BinaryData);
return response;
}
private string BuildInvoiceHtml(InvoiceRequest invoice)
{
return $@"<html><body>
<h1>Invoice #{invoice.Id}</h1>
<p>Amount: ${invoice.Amount:F2}</p>
</body></html>";
}
}
public record InvoiceRequest(string Id, decimal Amount);
using IronPdf;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace MyApp.Functions;
public class PdfFunctions
{
[Function("GenerateInvoice")]
public async Task<HttpResponseData> GenerateInvoice(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
var invoice = await req.ReadFromJsonAsync<InvoiceRequest>();
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice));
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
response.Headers.Add("Content-Disposition",
$"attachment; filename=invoice-{invoice.Id}.pdf");
await response.Body.WriteAsync(pdf.BinaryData);
return response;
}
private string BuildInvoiceHtml(InvoiceRequest invoice)
{
return $@"<html><body>
<h1>Invoice #{invoice.Id}</h1>
<p>Amount: ${invoice.Amount:F2}</p>
</body></html>";
}
}
public record InvoiceRequest(string Id, decimal Amount);
Consideração sobre implantação: O binário Chromium doIronPDFadiciona ~200 MB ao pacote de implantação. O plano de consumo do Azure Functions tem um limite de tamanho de implantação de 1,5 GB — verifique o tamanho total do seu pacote. Para planos Premium ou Dedicado, esse limite não se aplica. A latência inicial para a primeira geração de PDF é de 2–5 segundos enquanto o Chromium inicializa.
Compatibilidade com Native AOT
O .NET 8 expandiu o suporte para Native AOT, mas as bibliotecas de PDF enfrentam restrições fundamentais. Bibliotecas baseadas em Chromium (IronPDF, Puppeteer Sharp) não podem compilar AOT porque incorporam ou iniciam processos de navegador.iText 7usa reflexão extensiva que conflita com o trimming.
Status atual com <PublishAot>true</PublishAot>:
| Biblioteca | Status AOT | Razão |
|---|---|---|
| IronPDF | Não compatível | Incorpora runtime do Chromium |
| iText 7 | Não compatível | Reflexão pesada, geração de código dinâmico |
| QuestPDF | Parcial (com TrimMode=partial) |
Algum uso de reflexão |
| PdfSharp | Não compatível | Dependência de System.Drawing.Common |
Se o AOT Nativo é um requisito rígido,QuestPDFcom TrimMode=partial é a opção mais próxima — mas apenas para geração de documentos programática, não para conversão de HTML. Para cenários de HTML para PDF, AOT atualmente não é viável com nenhuma biblioteca.
Comparação de Licenciamento
| Biblioteca | Modelo | Custo | Suporte a .NET 8 |
|---|---|---|---|
| IronPDF | Perpétuo | $749 (Lite) / $1,499 (Pro) / $2,999 (Enterprise) | Completo |
| iText 7 | AGPL ou Assinatura | Não publicado (estimativa de $15K–$210K/ano) | Completo |
| QuestPDF | Comunidade / Comercial | Grátis <$1M de receita, depois comercial | Completo |
| PdfSharp | MIT (grátis) | $0 | Apenas Windows (Linux incompleto) |
| Aspose.PDF | Por desenvolvedor | ~$999+ | Completo (problemas de memória no Linux) |
Compatibilidade com .NET 9
.NET 9 (lançado em novembro de 2025) continua os padrões estabelecidos no .NET 8. As bibliotecas que funcionam com .NET 8 geralmente funcionam com .NET 9 sem alterações. As principais adições do .NET 9 relevantes para geração de PDF são o desempenho melhorado do ARM64 (beneficia a renderização baseada em Chromium no Apple Silicon e no AWS Graviton) e melhorias contínuas no Native AOT (embora as restrições fundamentais para bibliotecas de PDF permaneçam).
Se você está mirando o .NET 9 ou planejando atualizar, escolher uma biblioteca que suporte totalmente a implantação cross-platform do .NET 8 é o caminho mais seguro. Bibliotecas com problemas específicos de plataforma (PdfSharp no Linux, Aspose com libgdiplus) são improváveis de resolver esses problemas no .NET 9, pois a descontinuação da dependência subjacente é permanente.
Guia de Migração
De iTextSharp para IronPDF
// Before (iTextSharp — doesn't compile against net8.0)
using iTextSharp.text;
using iTextSharp.text.pdf;
var doc = new Document();
PdfWriter.GetInstance(doc, new FileStream("output.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
// After (IronPDF — targets net8.0)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>");
pdf.SaveAs("output.pdf");
// Before (iTextSharp — doesn't compile against net8.0)
using iTextSharp.text;
using iTextSharp.text.pdf;
var doc = new Document();
PdfWriter.GetInstance(doc, new FileStream("output.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
// After (IronPDF — targets net8.0)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>");
pdf.SaveAs("output.pdf");
De Wrappers do wkhtmltopdf para IronPDF
// Before (DinkToPdf — DllNotFoundException on .NET 8)
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlContent = html } }
};
var bytes = converter.Convert(doc);
// After (IronPDF — native .NET 8 support)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
var bytes = pdf.BinaryData;
// Before (DinkToPdf — DllNotFoundException on .NET 8)
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlContent = html } }
};
var bytes = converter.Convert(doc);
// After (IronPDF — native .NET 8 support)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
var bytes = pdf.BinaryData;
A superfície da API é mais simples em ambos os casos. O principal custo de migração é testar seus modelos HTML existentes contra o novo renderizador para verificar se a saída corresponde às expectativas.
A Recomendação
Para projetos .NET 8 que exigem conversão de HTML para PDF:IronPDFoferece renderização de Chromium embutida que funciona cross-platform sem configuração. Ele lida com implantação em Docker, Azure Functions e contêineres Linux automaticamente.
Para projetos .NET 8 construindo documentos programaticamente a partir de dados: a API fluente doQuestPDFé bem projetada e compatível com .NET 8, com a License da Comunidade cobrindo a maioria das startups e pequenas equipes.
Para manipulação de PDFs (mesclar, dividir, formulários) no Windows:PdfSharppermanece viável se seu alvo de implantação for apenas Windows.
Evite iTextSharp (incompatível), wrappers do wkhtmltopdf (arquivados, CVEs), e qualquer biblioteca que dependa do System.Drawing.Common para implantação cross-platform.