在C#项目里生成PDF报表是常见的业务需求,比如销售明细单、库存月报、财务对账单等。目前社区里讨论最多的两个方案是QuestPDF和iTextSharp。前者是近年崛起的新秀,采用声明式布局API;后者是老牌强者,功能覆盖面几乎无出其右。本文将从授权、API风格、代码示例和选型建议几个方面做一次完整的对比与实践讲解。

一、两个库的基本情况与授权差异
QuestPDF是一个纯.NET的开源库,由.NET社区开发者维护,它的设计理念受到Flutter的启发,用声明式的代码描述页面布局。安装非常简单,通过NuGet即可引入:
Install-Package QuestPDF
授权方面,QuestPDF采用社区许可协议,年收入低于100万美元的公司和个人可以免费用于商业用途,超过阈值则需要购买付费许可。对绝大多数中小团队来说,社区版完全够用,而且它没有功能阉割,社区版和付费版功能一致。
iTextSharp是iText在.NET平台上的移植版本,5.x版本之后官方主力转向了iText 7(.NET版本叫itext7)。iText系列采用AGPL授权,这意味着如果你的项目是闭源商业软件并且不打算开源,就必须购买商业授权,否则存在法律风险。这一点在做企业项目时一定要提前评估,很多团队因为忽视了授权问题后来被迫重构。
另外还有一点需要注意,iTextSharp 5.x已经停止维护,新项目建议直接使用itext7这个包,API更现代,文档也更完善。本文的iText示例将基于itext7来写。
二、API设计风格对比:声明式与命令式
QuestPDF最大的特点是流式布局,你不需要手动计算坐标,只需要描述“这里放一个标题,下面放一个表格,表格占据剩余空间”这样的结构意图,库会自动排版并处理分页。它的代码是用C#原生语法写DSL,属性和方法就是布局指令,可读性非常高。
iTextSharp(itext7)则是经典的命令式API,你需要先创建Document,然后逐个添加Paragraph、Table等元素。它的控制粒度极细,可以精确到每一个单元格的边框、每一个字体的度量,但代价是代码量偏大,嵌套较深时可读性下降。
下面分别用两个库生成同一份“销售报表”,直观感受差异。先看QuestPDF的写法:
using QuestPDF.Fuentes;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.Fluent;
public class SalesReportDocument : IDocument
{
public List<SalesRow> Rows { get; set; }
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(30);
page.Header().Text("月度销售报表").FontSize(18).Bold();
page.Content().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(40);
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Header(header =>
{
header.Cell().Text("序号");
header.Cell().Text("商品名称");
header.Cell().Text("数量");
header.Cell().Text("金额");
});
foreach (var row in Rows)
{
table.Cell().Text(Rows.IndexOf(row) + 1);
table.Cell().Text(row.ProductName);
table.Cell().Text(row.Quantity);
table.Cell().Text(row.Amount.ToString("C"));
}
});
page.Footer().AlignCenter().Text(text =>
{
text.CurrentPageNumber();
text.Span(" / ");
text.TotalPages();
});
});
}
}
// 调用生成
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container => new SalesReportDocument().Compose(container))
.GeneratePdf("sales-report.pdf");
可以看到,整个页面结构就像一棵布局树,Header、Content、Footer各司其职,分页逻辑全部自动处理。表格超出一页时会自动断行续页,表头也会在新页面重复出现,这些特性开箱即用。
再看itext7实现同样功能的写法:
using iText.IO.Font.Constants;
using iText.Kernel.Font;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
var writer = new PdfWriter("sales-report.pdf");
var pdf = new PdfDocument(writer);
var document = new Document(pdf, PageSize.A4);
document.SetMargins(30, 30, 30, 30);
var font = PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
document.Add(new Paragraph("月度销售报表")
.SetFont(font)
.SetFontSize(18)
.SetBold());
var table = new Table(UnitValue.CreatePercentArray(new float[] { 10, 40, 20, 30 }))
.UseAllAvailableWidth();
table.AddHeaderCell("序号");
table.AddHeaderCell("商品名称");
table.AddHeaderCell("数量");
table.AddHeaderCell("金额");
foreach (var row in salesRows)
{
table.AddCell((salesRows.IndexOf(row) + 1).ToString());
table.AddCell(row.ProductName);
table.AddCell(row.Quantity.ToString());
table.AddCell(row.Amount.ToString("C"));
}
document.Add(table);
document.Close();
itext7的代码同样清晰,但注意一个坑:默认字体Helvetica不支持中文,如果报表里有中文内容,必须加载外部字体文件,例如通过PdfFontFactory.CreateFont("C:/Windows/Fonts/simhei.ttf")来创建字体,否则中文会显示为空白。QuestPDF则默认使用系统中可用的字体渲染中文,通常不需要额外处理。
三、高级能力与性能表现对比
在高级功能层面,两者各有侧重。itext7的能力边界更广:数字签名、PDF/A归档、文档加密权限控制、表单填写AcroForm、PDF内容提取与合并拆分等,几乎涵盖了PDF标准的方方面面。如果你的需求不只是“生成”,还包括对已有PDF的深度处理,itext7几乎没有对手。
QuestPDF则专注于“生成”这件事,但它把生成体验做到了极致。它提供了一个实时预览工具,代码里调用.ShowInPreviewer()就能在开发时热刷新查看效果,改一行代码立即看到页面变化,调试布局的效率非常高。此外它还内置了图表元素、数据条形图、二维码生成等报表常用组件。
性能方面,QuestPDF基于SkiaSharp渲染,生成速度很快,生成几百页的报表通常在秒级完成,内存占用可控。itext7的性能同样优秀,尤其在纯文本表格场景下,两者差距不大。对于超大数据量的报表,建议都采用分批写入的策略,避免一次性把几十万行数据全部加载到内存里再渲染。
举个实际测量的例子:生成一份1万行数据、约300页的表格报表,QuestPDF在本机耗时约2秒,itext7约2.5秒,都在可接受范围内。真正的瓶颈往往在数据库查询而非PDF生成本身,所以选型时不必过分纠结渲染性能,重点看API顺手程度和授权成本。
四、如何选择:场景化的选型建议
如果项目是中小型业务系统,报表以表格和图文为主,团队追求开发效率和代码可维护性,QuestPDF是首选:免费、API现代、中文支持好、预览工具好用。声明式的布局代码在需求频繁变更时修改成本很低,产品经理要改个表头加个汇总行,往往只需几行代码。
如果项目对PDF有合规性要求,比如需要数字签名、需要生成符合PDF/A标准的归档文件、或者需要对已有PDF做合并、拆页、加水印、提取文本等操作,那么itext7更合适。此时要做的第一件事是确认授权:要么接受AGPL把项目开源,要么向官方购买商业许可,千万不要抱着侥幸心理直接用。
还有一种常见的组合方案:日常报表用QuestPDF生成,涉及签名盖章或文档归档的少数场景单独引入itext7处理。两个库都通过NuGet安装,互不冲突,按需分工反而能兼顾成本和功能。
最后提醒几个实践细节:第一,报表中涉及金额展示时统一用ToString("C")或格式化字符串,避免精度问题;第二,导出文件名包含中文时,Web场景下要对响应头做编码处理;第三,ASP.NET Core项目中建议把PDF生成放到后台任务或独立服务中,避免大报表阻塞请求线程。掌握这些要点后,无论选择哪个库,都能快速搭出一套稳定可靠的PDF报表导出能力。
QuestPDFiTextSharpC# PDF生成修改时间:2026-09-02 21:31:07