在ASP.NET中按指定模板导出Word和PDF文档,可通过OpenXML(Word)和QuestPDF(PDF)实现高效解决方案,以下是完整实现步骤:

Word导出实现(OpenXML)
核心流程:克隆模板文档 → 替换占位符 → 保存文件
// 安装NuGet包:DocumentFormat.OpenXml
public IActionResult ExportWord()
{
string templatePath = "Templates/report_template.docx";
string outputPath = "Output/report_output.docx";
// 克隆模板文件
System.IO.File.Copy(templatePath, outputPath, true);
// 打开文档修改内容
using (WordprocessingDocument doc = WordprocessingDocument.Open(outputPath, true))
{
var body = doc.MainDocumentPart.Document.Body;
foreach (var text in body.Descendants<Text>())
{
// 替换模板标记
if (text.Text.Contains("{CustomerName}"))
text.Text = text.Text.Replace("{CustomerName}", "张三科技有限公司");
if (text.Text.Contains("{ReportDate}"))
text.Text = text.Text.Replace("{ReportDate}", DateTime.Now.ToString("yyyy-MM-dd"));
}
}
return PhysicalFile(outputPath, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
}
关键技术点:

- 模板制作:在Word中直接插入
{CustomerName}等标记 - 动态表格:通过
Table类遍历添加行数据 - 样式保留:修改文本不影响原始格式
PDF导出实现(QuestPDF)
推荐方案:使用现代库QuestPDF替代iTextSharp(避免AGPL许可问题)
// 安装NuGet包:QuestPDF
public IActionResult ExportPdf()
{
var invoice = new InvoiceModel(
invoiceNumber: "INV-2026-085",
customerName: "李四集团",
items: new List<InvoiceItem> {
new ("网站开发", 2, 9800),
new ("服务器托管", 12, 650)
});
var document = Document.Create(container =>
{
container.Page(page =>
{
page.Content().Column(column =>
{
column.Item().Text($"发票号: {invoice.InvoiceNumber}");
column.Item().PaddingTop(20).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Header(header =>
{
header.Cell().Text("项目");
header.Cell().Text("数量");
header.Cell().Text("单价");
});
foreach (var item in invoice.Items)
{
table.Cell().Text(item.Name);
table.Cell().Text(item.Quantity.ToString());
table.Cell().Text(item.Price.ToString("C"));
}
});
});
});
});
var stream = new MemoryStream();
document.GeneratePdf(stream);
stream.Position = 0;
return File(stream, "application/pdf", "invoice.pdf");
}
进阶技巧
- 动态图片插入
// Word中插入图片 var imagePart = mainPart.AddImagePart(ImagePartType.Jpeg); using (var stream = new FileStream("logo.jpg", FileMode.Open)) { imagePart.FeedData(stream); } var drawing = new Drawing( new DW.Inline( new DW.Extent() { Cx = 500000, Cy = 200000 }, new DW.DocProperties() { Id = 1U, Name = "Logo" }, new Graphic(new GraphicData( new PIC.Picture( new PIC.NonVisualPictureProperties(...) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" } ) ) ); - PDF模板复用
// 复用已有PDF模板 container.Page(page => { page.Background().Image("background.jpg"); page.Content().Element(new InvoiceTemplate(invoice)); });
性能优化方案
| 操作类型 | 优化建议 | 效果提升 |
|---|---|---|
| 大数据量导出 | 分页生成+流式写入 | 内存降低70%+ |
| 高频访问场景 | 启用内存缓存输出结果 | 响应速度提升3倍 |
| 复杂模板 | 预编译模板结构 | 生成速度提升50% |
企业级解决方案
graph LR
A[数据库] --> B[.NET Core服务]
B --> C{导出类型}
C -->|Word| D[OpenXML模板引擎]
C -->|PDF| E[QuestPDF渲染器]
D --> F[Azure Blob存储]
E --> F
F --> G[CDN分发]
安全增强措施:

- 文件校验:添加SHA256数字指纹
- 防注入:清理模板中的XML特殊字符
- 访问控制:基于JWT的下载权限验证
遇到具体场景需要帮助?欢迎在评论区留言
问题示例:
- 如何在Word模板中处理动态表格合并单元格?
- 百万级数据导出怎样避免内存溢出?
- 如何实现PDF中的跨页表格表头重复?
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/22910.html