You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:32:56