在ASP.NET中按指定模板导出Word和PDF文档,可通过OpenXML(Word)和QuestPDF(PDF)实现高效解决方案,以下是完整实现步骤:
Word导出实现(OpenXML)
核心流程:克隆模板文档→替换占位符→保存文件
//安装NuGet包:DocumentFormat.OpenXmlpublicIActionResultExportWord(){stringtemplatePath="Templates/report_template.docx";stringoutputPath="Output/report_output.docx";//克隆模板文件System.IO.File.Copy(templatePath,outputPath,true);//打开文档修改内容using(WordprocessingDocumentdoc=WordprocessingDocument.Open(outputPath,true)){varbody=doc.MainDocumentPart.Document.Body;foreach(vartextinbody.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"));}}returnPhysicalFile(outputPath,"application/vnd.openxmlformats-officedocument.wordprocessingml.document");}
关键技术点:
- 模板制作:在Word中直接插入
{CustomerName}等标记
- 动态表格:通过
Table类遍历添加行数据
- 样式保留:修改文本不影响原始格式
PDF导出实现(QuestPDF)
推荐方案:使用现代库QuestPDF替代iTextSharp(避免AGPL许可问题)
//安装NuGet包:QuestPDFpublicIActionResultExportPdf(){varinvoice=newInvoiceModel(invoiceNumber:"INV-2026-085",customerName:"李四集团",items:newList<InvoiceItem>{new("网站开发",2,9800),new("服务器托管",12,650)});vardocument=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(varitemininvoice.Items){table.Cell().Text(item.Name);table.Cell().Text(item.Quantity.ToString());table.Cell().Text(item.Price.ToString("C"));}});});});});varstream=newMemoryStream();document.GeneratePdf(stream);stream.Position=0;returnFile(stream,"application/pdf","invoice.pdf");}
进阶技巧
- 动态图片插入
//Word中插入图片varimagePart=mainPart.AddImagePart(ImagePartType.Jpeg);using(varstream=newFileStream("logo.jpg",FileMode.Open)){imagePart.FeedData(stream);}vardrawing=newDrawing(newDW.Inline(newDW.Extent(){Cx=500000,Cy=200000},newDW.DocProperties(){Id=1U,Name="Logo"},newGraphic(newGraphicData(newPIC.Picture(newPIC.NonVisualPictureProperties(...)){Uri="http://schemas.openxmlformats.org/drawingml/2006/picture"})));
- PDF模板复用
//复用已有PDF模板container.Page(page=>{page.Background().Image("background.jpg");page.Content().Element(newInvoiceTemplate(invoice));});
性能优化方案
| 操作类型 |
优化建议 |
效果提升 |
| 大数据量导出 |
分页生成+流式写入 |
内存降低70%+ |
| 高频访问场景 |
启用内存缓存输出结果 |
响应速度提升3倍 |
| 复杂模板 |
预编译模板结构 |
生成速度提升50% |
企业级解决方案
graphLRA[数据库]-->B[.NETCore服务]B-->C{导出类型}C-->WordD[OpenXML模板引擎]C-->PDFE[QuestPDF渲染器]D-->F[AzureBlob存储]E-->FF-->G[CDN分发]
安全增强措施:
- 文件校验:添加SHA256数字指纹
- 防注入:清理模板中的XML特殊字符
- 访问控制:基于JWT的下载权限验证
遇到具体场景需要帮助?欢迎在评论区留言
问题示例:
- 如何在Word模板中处理动态表格合并单元格?
- 百万级数据导出怎样避免内存溢出?
- 如何实现PDF中的跨页表格表头重复?