.NET Framework Web API集成QuestPDF生成PDF异常求助
.NET Framework Web API中QuestPDF生成PDF显示异常的解决方法
问题场景
控制台应用中使用QuestPDF可正常生成PDF,但在.NET Framework Web API的DownloadController中实现相同逻辑时,返回的PDF显示异常。
原代码
using System.Web.Http; using System.Web.Mvc; using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; using SkiaSharp; using System.IO; namespace Questpdf2.Controllers { public class DownloadController : ApiController { [System.Web.Mvc.HttpGet] public FileStreamResult GetPDF() { byte[] pdfBytes = Document.Create(document => { document.Page(page => { page.Margin(2, Unit.Centimetre); page.DefaultTextStyle(x => x.FontSize(12)); page.Header() .Row(row => { row.Spacing(25); row.ConstantItem(100) .Height(100) .Width(50) .Image("C:\\Users\\Administrator\\Documents\\HAMS\\New folder\\Questpdf2\\image\\im.png", ImageScaling.Resize); row.RelativeItem() .Column(column => { column.Item() .Text("My header") .SemiBold() .FontSize(30) .FontColor(Colors.Blue.Medium); column.Item() .Text("Q&A Table") .Underline() .FontSize(20) .FontColor(Colors.Blue.Medium); }); }); page.Content() .PaddingVertical(25).Table(table => { table.ColumnsDefinition(columns => { columns.ConstantColumn(50); columns.RelativeColumn(); columns.RelativeColumn(); columns.ConstantColumn(60); columns.ConstantColumn(60); }); table.Header(header => { header.Cell().Text("S.No"); header.Cell().AlignRight().Text("Question"); header.Cell().AlignRight().Text("QType"); header.Cell().AlignRight().Text("Weightage"); header.Cell().AlignRight().Text("Sortorder"); }); table.Cell().Text("1"); table.Cell().Text("what is the important aspects of IT?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("6"); table.Cell().Text("2"); table.Cell().Text("an extension of image file?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("1"); table.Cell().Text("3"); table.Cell().Text("What are security controls?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("7"); table.Cell().Text("4"); table.Cell().Text("compliance standard?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("2"); table.Cell().Text("5"); table.Cell().Text("Risk is the failure in component?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("3"); table.Cell().Text("6"); table.Cell().Text("Third party tools in software?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("5"); table.Cell().Text("7"); table.Cell().Text("What are cloud based solutions?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("4"); }); page.Footer() .AlignCenter() .Text(text => { text.DefaultTextStyle(x => x.FontSize(15)); text.Span("Page number").FontSize(10); text.CurrentPageNumber(); text.Span(" out of "); text.TotalPages(); }); }); }).GeneratePdf(); MemoryStream ms = new MemoryStream(pdfBytes); return new FileStreamResult(ms, "application/pdf"); } } }
问题分析与修复步骤
1. 控制器与返回类型混用问题
ApiController是Web API专用控制器,不应返回MVC的FileStreamResult,同时System.Web.Mvc.HttpGet特性也不适合Web API,需替换为Web API对应类型。
2. MemoryStream位置未重置
将字节数组写入MemoryStream后,流的指针停在末尾,需重置到起始位置,否则读取时会从空位置开始,导致PDF内容损坏。
3. 图片路径硬编码问题
Web应用运行上下文与控制台不同,硬编码本地路径易引发权限问题或文件找不到,建议改用相对路径或通过配置获取路径。
修复后的代码
using System.Web.Http; using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; using System.IO; using System.Net.Http; using System.Net.Http.Headers; namespace Questpdf2.Controllers { public class DownloadController : ApiController { [HttpGet] public IHttpActionResult GetPDF() { byte[] pdfBytes = null; try { pdfBytes = Document.Create(document => { document.Page(page => { page.Margin(2, Unit.Centimetre); page.DefaultTextStyle(x => x.FontSize(12)); page.Header() .Row(row => { row.Spacing(25); // 使用Web应用相对路径获取图片 var imagePath = Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~/image"), "im.png"); row.ConstantItem(100) .Height(100) .Width(50) .Image(imagePath, ImageScaling.Resize); row.RelativeItem() .Column(column => { column.Item() .Text("My header") .SemiBold() .FontSize(30) .FontColor(Colors.Blue.Medium); column.Item() .Text("Q&A Table") .Underline() .FontSize(20) .FontColor(Colors.Blue.Medium); }); }); page.Content() .PaddingVertical(25).Table(table => { table.ColumnsDefinition(columns => { columns.ConstantColumn(50); columns.RelativeColumn(); columns.RelativeColumn(); columns.ConstantColumn(60); columns.ConstantColumn(60); }); table.Header(header => { header.Cell().Text("S.No"); header.Cell().AlignRight().Text("Question"); header.Cell().AlignRight().Text("QType"); header.Cell().AlignRight().Text("Weightage"); header.Cell().AlignRight().Text("Sortorder"); }); table.Cell().Text("1"); table.Cell().Text("what is the important aspects of IT?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("6"); table.Cell().Text("2"); table.Cell().Text("an extension of image file?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("1"); table.Cell().Text("3"); table.Cell().Text("What are security controls?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("7"); table.Cell().Text("4"); table.Cell().Text("compliance standard?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("2"); table.Cell().Text("5"); table.Cell().Text("Risk is the failure in component?"); table.Cell().AlignRight().Text("Choice"); table.Cell().AlignRight().Text("2"); table.Cell().AlignRight().Text("3"); table.Cell().Text("6"); table.Cell().Text("Third party tools in software?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("5"); table.Cell().Text("7"); table.Cell().Text("What are cloud based solutions?"); table.Cell().AlignRight().Text("Essay"); table.Cell().AlignRight().Text("5"); table.Cell().AlignRight().Text("4"); }); page.Footer() .AlignCenter() .Text(text => { text.DefaultTextStyle(x => x.FontSize(15)); text.Span("Page number").FontSize(10); text.CurrentPageNumber(); text.Span(" out of "); text.TotalPages(); }); }); }).GeneratePdf(); } catch (Exception ex) { return InternalServerError(ex); } var ms = new MemoryStream(pdfBytes); ms.Position = 0; // 重置流指针到起始位置 return new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StreamContent(ms) { Headers = { ContentType = new MediaTypeHeaderValue("application/pdf"), ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "QATable.pdf" } } } }.Result; } } }
额外注意事项
- 确保Web应用程序池对图片路径有读取权限
- 可输出
pdfBytes长度确认是否生成有效数据 - 保持QuestPDF版本与控制台应用一致,避免版本兼容问题
内容的提问来源于stack exchange,提问作者ani H
相关产品推荐
相关产品推荐

