How to stream with ASP.NET Core

2019-02-05 02:47发布

问题:

How to properly stream response in ASP.NET Core? There is a controller like this (UPDATED CODE):

[HttpGet("test")]
public async Task GetTest()
{
    HttpContext.Response.ContentType = "text/plain";
    using (var writer = new StreamWriter(HttpContext.Response.Body))
        await writer.WriteLineAsync("Hello World");            
}

Firefox/Edge browsers show

Hello World

, while Chrome/Postman report an error:

The localhost page isn’t working

localhost unexpectedly closed the connection.

ERR_INCOMPLETE_CHUNKED_ENCODING

P.S. I am about to stream a lot of content, so I cannot specify Content-Length header in advance.

回答1:

To stream a response that should appear to the browser like a downloaded file, you should use FileStreamResult:

[HttpGet]
public FileStreamResult GetTest()
{
  var stream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World"));
  return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
  {
    FileDownloadName = "test.txt"
  };
}


回答2:

It is possible to return null or EmptyResult() (which are equivalent), even when previously writing to Response.Body. It may be useful if the method returns ActionResult to be able to use all the other results aswell (e.g. BadQuery()) easily.

[HttpGet("test")]
public ActionResult Test()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/plain";
    using (var sw = new StreamWriter(Response.Body))
    {
        sw.Write("something");
    }
    return null;
}


回答3:

I was wondering as well how to do this, and have found out that the original question's code actually works OK on ASP.NET Core 2.1.0-rc1-final, neither Chrome (and few other browsers) nor JavaScript application do not fail with such endpoint.

Minor things I would like to add are just set StatusCode and close the response Stream to make the response fulfilled:

[HttpGet("test")]
public void Test()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/plain";
    using (Response.Body)
    {
        using (var sw = new StreamWriter(Response.Body))
        {
            sw.Write("Hi there!");
        }
    }
}


回答4:

something like this might work:

[HttpGet]
public async Task<IActionResult> GetTest()
{
    var contentType = "text/plain";
    using (var stream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World")))
    return new FileStreamResult(stream, contentType);

}