比较

为 .NET 8 选择文档生成库

.NET 8 引入了运行时更改,破坏了与许多传统 PDF 库的兼容性。 System.Drawing.Common 在非 Windows 平台上已被弃用,原生 AOT 对大量使用反射的库施加了新的限制,并且容器优先部署模型暴露了在 Windows 开发机器上未出现的依赖性问题。 在 .NET Framework 甚至 .NET 6 中可以正常运行的库在 .NET 8 中可能会出现NU1202DllNotFoundExceptionPlatformNotSupportedException错误。

本文记录了哪些 PDF 库可与 .NET 8 配合使用,展示了与不兼容的库一起使用时会遇到的具体错误,并提供了 Docker 和 Azure Functions 的部署配置。

快速入门:在 .NET 8 中从 HTML 生成 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");
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");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4

Dim 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")
$vbLabelText   $csharpLabel

通过 NuGet 安装: Install-Package IronPdf 。 无需额外配置即可面向net8.0 。 无需针对特定平台进行设置,即可部署到 Windows、Linux、macOS、Docker 和 Azure。

为什么旧版 PDF 库在 .NET 8 中无法正常工作?

iTextSharp — 与 .NET 8 不兼容

iTextSharp(iText 的原始 .NET 版本)自 2018 年以来就未更新过。它仅面向 .NET Framework:

错误 NU1202:iTextSharp 5.5.13 程序包与 net8.0 不兼容。

迁移路径是 iText 7,它具有不同的 API,并且需要遵守 AGPL 协议(开源您的整个应用程序)或获得商业许可。 价格未公开——第三方数据显示每年费用为 15,000 美元至 210,000 美元。

wkhtmltopdf 封装器 — .NET 8 上的 DLL 加载失败

对 wkhtmltopdf 的 C# 封装(DinkToPdf、Rotativa、NReco.PdfGenerator)会因 .NET 8 部署模型特有的平台特定错误而失败:

DinkToPdf — 未找到本地库:

System.DllNotFoundException:无法加载 DLL"libwkhtmltox"

Rotativa.AspNetCore — 需要手动配置二进制文件路径,这与 .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");
' This pattern requires deploying wkhtmltopdf binaries alongside your app
' and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf")
$vbLabelText   $csharpLabel

TuesPechkin / NReco — 架构不匹配:

System.BadImageFormatException:无法加载文件或程序集

这些错误反映了一个更深层次的问题:wkhtmltopdf于 2024 年 7 月存档,但其中存在的 CVE 漏洞尚未修复。 原生二进制架构早于 .NET 8 的平台检测改进。 没有解决办法——只能迁移到另一个库。

PdfSharp— Linux 系统绘图常见故障

PdfSharp 依赖于 System.Drawing.Common,而微软在 .NET 6 中已弃用其在非 Windows 平台上的兼容性。在 .NET 8 中,当部署到 Linux 或 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
Imports PdfSharp.Pdf
Imports PdfSharp.Drawing

Dim document As New PdfDocument()
' PlatformNotSupportedException on Linux:
' System.Drawing.Common is not supported on this platform
$vbLabelText   $csharpLabel

PdfSharp 6.x 一直在努力消除这种依赖性,但截至 2026 年初,跨平台支持仍不完善。对于仅限 Windows 的部署,PdfSharp 可与 .NET 8 配合使用。对于 Linux、Docker 或云部署,其兼容性不稳定。

哪些 PDF 库与 .NET 8 兼容?

IronPDF— 完全支持 .NET 8,跨平台

IronPDF 原生支持net8.0 ,并内置 Chromium 渲染。 不依赖 System.Drawing.Common,不进行本地二进制管理,不进行平台特定的配置。

最小化 API 集成(.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();
Imports IronPdf

Dim builder = WebApplication.CreateBuilder(args)
Dim app = builder.Build()

app.MapGet("/invoice/{id}/pdf", Async Function(id As Integer, service As InvoiceService) 
    Dim invoice = Await service.GetInvoiceAsync(id)
    Dim renderer = New ChromePdfRenderer()

    Dim pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml())

    Return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf")
End Function)

app.Run()
$vbLabelText   $csharpLabel

对于使用控制器模式的团队来说,相同的代码可以在控制器操作中运行RenderHtmlAsPdf返回一个PdfDocument ,您可以使用.BinaryData将其转换为字节。

许可:永久许可起价 749 美元(精简版 — 1 位开发者,1 个项目)。 专业版:1499 美元(10 位开发人员)。 企业版:2,999 美元(无限制)。 发布于ironpdf.com

QuestPDF— 兼容 .NET 8,无需 HTML

QuestPDF 可与 .NET 8 配合使用,无需平台依赖。 它流畅的 C# API 以编程方式构建文档——无需 HTML 解析器、CSS 引擎或浏览器引擎:

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");
Imports QuestPDF.Fluent
Imports QuestPDF.Infrastructure

QuestPDF.Settings.License = LicenseType.Community ' Free under $1M revenue

Document.Create(Sub(container)
    container.Page(Sub(page)
        page.Size(PageSizes.A4)
        page.Margin(2, Unit.Centimetre)
        page.Content().Column(Sub(col)
            col.Item().Text("Q4 Report").FontSize(24).Bold()
            col.Item().Table(Sub(table)
                table.ColumnsDefinition(Sub(c)
                    c.RelativeColumn(2)
                    c.RelativeColumn(1)
                    c.RelativeColumn(1)
                End Sub)
                table.Header(Sub(h)
                    h.Cell().Text("Metric").Bold()
                    h.Cell().Text("Value").Bold()
                    h.Cell().Text("Change").Bold()
                End Sub)
                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%")
            End Sub)
        End Sub)
    End Sub)
End Sub).GeneratePdf("report.pdf")
$vbLabelText   $csharpLabel

QuestPDF 不转换 HTML。 如果您的工作流程使用 HTML 模板(Razor 视图、仪表板导出、Web 内容归档),则需要不同的库。 社区许可证适用于年收入低于 100 万美元的企业; 此外,还需要商业许可

iText 7— 兼容 .NET 8,AGPL 许可

iText 7(iTextSharp 的继任者)支持 .NET 8。pdfHTML 插件使用自定义解析器提供 HTML 到 PDF 的转换,而不是浏览器引擎,因此现代 CSS 功能(Flexbox、Grid)无法正确渲染。

许可:开源用途采用AGPL 许可,专有应用程序采用商业许可(订阅,价格未公布)。 iText 于 2024 年转型为基于订阅的商业许可模式

Docker 部署

标准 Debian 镜像(推荐)

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"]

高山影像(占地面积更小)

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"]

Debian镜像不需要任何额外的软件包。 Alpine镜像文件较小,但需要显式安装Chromium库。 对于大多数部署而言,标准的 Debian 镜像更简单、更可靠。

Azure Functions(独立工作进程)

.NET 8 Azure Functions 使用隔离工作器模型。 IronPDF采用这种模式实现按需PDF生成:

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);
Imports IronPdf
Imports Microsoft.Azure.Functions.Worker
Imports Microsoft.Azure.Functions.Worker.Http

Namespace MyApp.Functions

    Public Class PdfFunctions

        <Function("GenerateInvoice")>
        Public Async Function GenerateInvoice(
            <HttpTrigger(AuthorizationLevel.Function, "post")> req As HttpRequestData) As Task(Of HttpResponseData)

            Dim invoice = Await req.ReadFromJsonAsync(Of InvoiceRequest)()

            Dim renderer = New ChromePdfRenderer()
            Dim pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice))

            Dim 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
        End Function

        Private Function BuildInvoiceHtml(invoice As InvoiceRequest) As String
            Return $"<html><body>
            <h1>Invoice #{invoice.Id}</h1>
            <p>Amount: ${invoice.Amount:F2}</p>
        </body></html>"
        End Function

    End Class

    Public Class InvoiceRequest
        Public Property Id As String
        Public Property Amount As Decimal

        Public Sub New(id As String, amount As Decimal)
            Me.Id = id
            Me.Amount = amount
        End Sub
    End Class

End Namespace
$vbLabelText   $csharpLabel

部署注意事项:IronPDF的 Chromium 二进制文件会使部署包增加约 200MB。 Azure Functions 消耗计划的部署大小限制为 1.5GB - 请核实您的总包大小。高级版或专用版计划不受此限制。 由于 Chromium 初始化,首次生成 PDF 的冷启动延迟为 2-5 秒。

原生 AOT 兼容性

.NET 8 扩展了原生 AOT 支持,但 PDF 库面临根本性的限制。 基于 Chromium 的库(IronPDF、Puppeteer Sharp)无法编译 AOT,因为它们嵌入或生成浏览器进程。iText 7使用了大量的反射功能,这与裁剪功能相冲突。

当前状态<PublishAot>true</PublishAot>

AOT状态原因
IronPDF不兼容嵌入 Chromium 运行时
iText 7不兼容深度反射,动态代码生成
QuestPDF部分( TrimMode=partial一些反思用法
PdfSharp不兼容系统.绘图.通用依赖关系

如果原生 AOT 是一个硬性要求,那么TrimMode=partial的QuestPDF是最接近的选择——但仅适用于程序化文档生成,不适用于 HTML 转换。 对于 HTML 转 PDF 的场景,目前没有任何库支持 AOT。

许可比较

模型成本.NET 8 支持
IronPDF永久749 美元(精简版)/ 1,499 美元(专业版)/ 2,999 美元(企业版)满的
iText 7AGPL 或订阅未公布(估计年薪 1.5 万至 21 万美元)满的
QuestPDF社区/商业免费,收入低于 100 万美元,然后商业化满的
PdfSharp麻省理工学院(免费)$0仅限 Windows 系统(Linux 系统功能不完整)
Aspose.PDF每个开发人员约999美元以上内存不足(Linux 内存问题)

.NET 9 向前兼容性

.NET 9(2025 年 11 月发布)延续了 .NET 8 中建立的模式。与 .NET 8 兼容的库通常无需更改即可与 .NET 9 兼容。 与 PDF 生成相关的 .NET 9 的主要新增功能包括改进的 ARM64 性能(有利于 Apple Silicon 和 AWS Graviton 上的基于 Chromium 的渲染)以及持续的 Native AOT 改进(尽管 PDF 库的基本限制仍然存在)。

如果您的目标是 .NET 9 或计划升级,那么选择一个完全支持 .NET 8 跨平台部署的库是最安全的途径。 存在平台特定问题的库(例如 Linux 上的 PdfSharp、带有 libgdiplus 的 Aspose)不太可能在 .NET 9 中解决这些问题,因为底层依赖项的弃用是永久性的。

迁移指南

从 iTextSharp 到 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");
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports IronPdf
Imports System.IO

' Before (iTextSharp — doesn't compile against net8.0)
Dim doc As 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)
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>")
pdf.SaveAs("output.pdf")
$vbLabelText   $csharpLabel

从 wkhtmltopdf 封装器到 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;
Imports IronPdf

' Before (DinkToPdf — DllNotFoundException on .NET 8)
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument With {
    .Objects = {New ObjectSettings With {.HtmlContent = html}}
}
Dim bytes = converter.Convert(doc)

' After (IronPDF — native .NET 8 support)
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
bytes = pdf.BinaryData
$vbLabelText   $csharpLabel

两种情况下,API接口都更简单。 迁移的主要成本是使用新的渲染器测试现有的 HTML 模板,以验证输出是否符合预期。

建议

对于需要将 HTML 转换为 PDF 的 .NET 8 项目:IronPDF 提供嵌入式 Chromium 渲染,无需配置即可跨平台工作。 它开箱即用,可处理 Docker 部署、Azure Functions 和 Linux 容器。

对于使用 .NET 8 以编程方式从数据构建文档的项目:QuestPDF 的流畅 API 设计精良,与 .NET 8 兼容,社区许可证涵盖了大多数初创公司和小团队。

对于 Windows 上的 PDF 处理(合并、拆分、表单):如果您的部署目标仅限于 Windows,则PdfSharp仍然可用。

避免使用 iTextSharp(不兼容)、wkhtmltopdf 包装器(已存档,存在 CVE)以及任何依赖于 System.Drawing.Common 的库进行跨平台部署。