questpdf 最轻量可控但需手动映射html结构;wkhtmltopdf支持完整css/js但依赖外部进程且性能低;webview2渲染完美但部署复杂且仅限windows;中文乱码需统一utf-8编码并注意字体处理。

用 QuestPDF 生成 PDF 最轻量且可控
如果你只是把简单 HTML 片段(比如报表、邮件模板)转成 PDF,QuestPDF 是目前 C# 生态里最干净的选择——它不依赖系统组件、不调用外部浏览器进程、纯 .NET 实现,且能精确控制布局。但它不解析 HTML 字符串,需要你手动把 HTML 结构映射为 QuestPDF 的 API 调用。
典型做法是:用 HtmlAgilityPack 解析 HTML,再遍历节点,对 <p></p>、<h1></h1>、<table> 等标签分别调用 <code>Container、Text、Table 等构建器。表格和样式支持有限,比如 colspan 可以处理,但 CSS Flex/Grid 完全不识别。
示例片段(渲染一个带标题和段落的简单页面):
var doc = Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(20);
page.Content().Element(ComposeTitle);
});
});
<p>doc.GeneratePdf("output.pdf");</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><p>void ComposeTitle(IContainer container)
{
container
.PaddingVertical(10)
.Text("Hello World").FontSize(24).Bold();
container
.PaddingVertical(5)
.Text("This is a paragraph.").FontSize(12);
}用 Wkhtmltopdf + Rotativa 或 HtmlToPdf 库做“真 HTML 渲染”
当你需要保留 CSS 样式、字体、媒体查询甚至 JavaScript 渲染后的内容(比如 ECharts 图表截图),就得走 WebKit 渲染路线。Wkhtmltopdf 是底层引擎,Windows/macOS/Linux 都有预编译二进制,C# 通过进程调用或封装库驱动它。
Rotativa.AspNetCore(ASP.NET Core)或 HtmlToPdf(.NET Standard)是常用封装,它们本质都是启动 wkhtmltopdf.exe 并传参。关键点:
-
--no-stop-slow-scripts必加,否则 JS 执行超时会截断内容 -
--enable-local-file-access要开,否则file://引用的 CSS/图片加载失败 - 字体问题常见:Windows 上默认用 SimSun,Linux 上可能缺中文字体,需提前安装并用
@font-face指向绝对路径 - 生成时间不可控,单次调用通常 300–800ms,高并发下建议加进程池或改用服务化部署(如独立 PDF 渲染 API)
Microsoft.Web.WebView2 在 .NET 6+ 中可离线渲染但极难稳定
WebView2 基于 Edge Chromium,理论上能完美渲染任意 HTML。但把它用于服务端 PDF 导出,实际踩坑密集:
必须显式创建 CoreWebView2Environment 并指定固定用户数据文件夹,否则多线程下 WebView2 初始化失败;导出 PDF 需调用 PrintToPdfAsync,而该方法仅在 UI 线程可用——意味着你得在后台线程里伪造一个 WinForms/WPF 消息循环,或改用 Dispatcher 调度,极易死锁。
更现实的问题是:它强制依赖目标机器安装 WebView2 Runtime(约 180MB),无法 AOT 发布,且 Linux/macOS 不支持。除非你已锁定 Windows 桌面环境并控制全部部署条件,否则不建议选这条路。
别忽略编码与中文乱码这个高频故障点
所有方案都可能在含中文的 HTML 中输出方块或空格,根源几乎全是编码声明缺失或不一致:
- HTML 字符串开头必须有
<meta charset="utf-8">,且 HTTP 响应头(如果走 URL 加载)也要设Content-Type: text/html; charset=utf-8 - 用
File.ReadAllText(path, Encoding.UTF8)读取本地 HTML 文件,别依赖默认编码 -
Wkhtmltopdf若仍乱码,尝试加参数--encoding utf-8(部分旧版本不支持,需 v0.12.6+) - CSS 中避免用系统字体名(如
"微软雅黑"),改用通用族名font-family: sans-serif,或确保 PDF 引擎能访问对应 TTF 文件
真正麻烦的是混合场景:HTML 里有 Base64 图片、内联 SVG、动态 fetch 数据——这些都会让转换链路变脆弱。与其强求一步到位,不如把 HTML 拆成「静态结构 + JSON 数据」,用模板引擎(如 Scrutor 或 Fluid)先渲染为纯净 HTML,再交给 PDF 工具处理。











