.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.WebApiCompatShimNuGet包 ResponseMessageResult会告诉框架将HttpResponseMessage转换为原生HTTP响应,而非序列化
内容的提问来源于stack exchange,提问作者Modestas Vacerskas
相关产品推荐
相关产品推荐

