ASP.NET Core 2 控制器的 ActionMethod async Task 返回 HttpResponseMessage。
ASP.NET Core 2 控制器的 ActionMethod async Task 返回 HttpResponseMessage。
问题:
我想在我的ASP.Net Web API Controller中返回一个文件,但是我所有的方法都将HttpResponseMessage
返回为JSON。
目前的代码:
public async TaskDownloadAsync(string id) { var response = new HttpResponseMessage(HttpStatusCode.OK); response.Content = new StreamContent({{__insert_stream_here__}}); response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); return response; }
当我在浏览器中调用这个端点时,Web API返回的HttpResponseMessage
是JSON,HTTP Content Header设置为application/json
。
ASP.NET Core 2中,Controller的ActionMethod异步返回HttpresponseMessage的问题出现的原因是在代码中混合使用了不同的Web API版本。解决方法是将Action返回一个派生自IActionResult的类型,因为在当前的代码中,框架将HttpResponseMessage视为一个模型。
以下是解决问题的代码示例:
[Route("api/[controller]")] public class DownloadController : Controller { //GET api/download/12345abc [HttpGet("{id}")] public async TaskDownload(string id) { Stream stream = await {{__get_stream_based_on_id_here__}} if(stream == null) return NotFound(); // 返回一个NotFoundResult,状态码为404 return File(stream, "application/octet-stream", "{{filename.ext}}"); // 返回一个FileStreamResult } }
需要注意的是,当响应完成时,框架会自动释放使用的流。如果在代码中使用了`using`语句,流将在响应发送之前被释放,这可能导致异常或损坏的响应。在某些情况下,可能需要在内存中生成Excel并返回下载,这时需要在返回语句中指定文件名和扩展名,例如:`return File(stream, "application/octet-stream", "filename.xlsx");` 这样当用户下载文件时可以直接打开。
关于`NotFound()`方法的说明,它是`ControllerBase`的一个辅助方法,是框架本身的一部分。可以在Microsoft官方文档中查看详情。
在某些情况下,可能需要根据URL从源获取文件并以分块的方式将其流式传输给客户端。可以参考这个链接中的讨论,以获取更多相关信息。
需要注意的是,在这个特定的代码示例中不需要使用`using`语句。框架会在响应完成时自动释放流。如果在代码中使用了`using`语句,流将在响应发送之前被释放。可以通过查看源代码这里来了解实际将流写入响应的源代码。
最后,还有一个关于将流转换为字节数组并在返回语句中返回字节数组的问题。这种方法适用于在Postman中测试时,可以将流转换为字节数组,并在返回语句中使用`File(byte[], mimetype)`的方式返回字节数组。这个方法可以通过在返回语句中指定文件名来解决一些问题。
以上是关于ASP.NET Core 2中Controller的ActionMethod异步返回HttpresponseMessage的问题的原因和解决方法的整理。希望对你有帮助!
在上述代码中,控制器的ActionMethod是一个异步方法,返回类型为Task<FileStreamResult>
,它用于下载文件。然而,在某些情况下,开发人员可能会尝试将返回类型更改为async Task<FileResult>
,例如HttpResponseMessage
,以实现更多的自定义操作。
这样的更改可能会导致编译错误或运行时错误,原因是FileResult
和HttpResponseMessage
是不兼容的类型。解决这个问题的方法是将返回类型更改回FileStreamResult
,或者根据具体需求使用其他适当的返回类型,而不是强制使用HttpResponseMessage
。
以下是修复问题的示例代码:
using System.IO; using Microsoft.AspNetCore.Mvc;
[HttpGet("{id}")] public async Task<FileStreamResult> Download(int id) { var path = "<Get the file path using the ID>"; var stream = File.OpenRead(path); return new FileStreamResult(stream, "application/octet-stream"); }
请注意,确保使用Microsoft.AspNetCore.Mvc
中的FileStreamResult
,而不是System.Web.Mvc
中的FileStreamResult
。