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

.NET6 WebAPI下载PDF返回JSON未自动下载,需如何修改?

.NET6 WebAPI 返回JSON而非自动下载PDF的解决方法

我正在学习使用C# .NET6 WebAPI下载PDF文件的教程,已完全按照教程步骤操作,但得到了与教程不同的响应。点击链接后没有自动下载PDF,而是返回了一个JSON对象:

{"version":"1.1","content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=FileTest.pdf"]},{"key":"Content-Type","value":["application/pdf"]},{"key":"Content-Length","value":["362671"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"trailingHeaders":[],"requestMessage":null,"isSuccessStatusCode":true}

原代码如下:

[HttpGet]
[Route("GetPdf")]
public HttpResponseMessage Get()
{
    HttpResponseMessage result = new HttpResponseMessage(System.Net.HttpStatusCode.OK);

    string pdfLocation = _webHostEnvironment.WebRootPath + "\\PDF\\Biletas.pdf";

    var stream = new MemoryStream(System.IO.File.ReadAllBytes(pdfLocation));
    stream.Position = 0;

    if (stream == null)
    {
        result = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
        return result;
    }

    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");

    result.Content.Headers.ContentDisposition.FileName = "FileTest.pdf";
    result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");

    result.Content.Headers.ContentLength = stream.Length;


    return result;
}

问题根源

在.NET Core/.NET 6+中,直接返回HttpResponseMessage会被框架自动序列化为JSON,而非作为原生HTTP响应发送给客户端——这是ASP.NET Core与旧版ASP.NET Web API的核心行为差异。

两种修改方案

方案1:使用FileStreamResult返回(推荐)

ASP.NET Core提供了专门的文件返回类型,更贴合框架设计,代码更简洁:

using Microsoft.AspNetCore.Mvc;
using System.IO;

[HttpGet]
[Route("GetPdf")]
public IActionResult Get()
{
    string pdfLocation = Path.Combine(_webHostEnvironment.WebRootPath, "PDF", "Biletas.pdf");

    if (!System.IO.File.Exists(pdfLocation))
    {
        return BadRequest();
    }

    var stream = new FileStream(pdfLocation, FileMode.Open, FileAccess.Read);
    return File(stream, "application/pdf", "FileTest.pdf");
}
  • 用Path.Combine替代硬编码的路径拼接,避免跨平台路径分隔符问题
  • 提前检查文件是否存在,比判断流是否为空更可靠
  • File()方法会自动配置Content-Disposition、Content-Type等响应头,无需手动设置

方案2:适配HttpResponseMessage(兼容旧代码)

如果需要保留HttpResponseMessage的写法,需要用ResponseMessageResult包装返回:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.WebApiCompatShim;
using System.IO;

[HttpGet]
[Route("GetPdf")]
public IActionResult Get()
{
    HttpResponseMessage result = new HttpResponseMessage(System.Net.HttpStatusCode.OK);

    string pdfLocation = Path.Combine(_webHostEnvironment.WebRootPath, "PDF", "Biletas.pdf");

    if (!System.IO.File.Exists(pdfLocation))
    {
        result = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
        return new ResponseMessageResult(result);
    }

    var stream = new MemoryStream(System.IO.File.ReadAllBytes(pdfLocation));
    stream.Position = 0;

    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = "FileTest.pdf";
    result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
    result.Content.Headers.ContentLength = stream.Length;

    return new ResponseMessageResult(result);
}
  • 需要确保项目已引用Microsoft.AspNetCore.Mvc.WebApiCompatShim NuGet包
  • ResponseMessageResult会告诉框架将HttpResponseMessage转换为原生HTTP响应,而非序列化

内容的提问来源于stack exchange,提问作者Modestas Vacerskas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:15:41