如何使用ASP.NET Core进行流传输

问题描述 投票:18回答:5

如何在ASP.NET Core中正确流式传输响应?有一个像这样的控制器(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浏览器显示

Hello World

,而Chrome /邮递员报告错误:

本地主机页面不起作用

localhost意外关闭了连接。

ERR_INCOMPLETE_CHUNKED_ENCODING

P.S。我将要流式传输许多内容,因此无法提前指定Content-Length标头。

c# asp.net-core asp.net-core-mvc asp.net-core-1.0
5个回答
23
投票

[流式传输应像下载文件一样显示在浏览器中的响应,您应使用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"
  };
}

4
投票

即使先前写入null时,也可能返回EmptyResult()Response.Body(等效)。如果该方法返回ActionResult以便能够轻松使用所有其他结果(例如BadQuery()),则可能会很有用。

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

2
投票

我也想知道如何做到这一点,并且发现原始问题的代码实际上可以在ASP.NET Core 2.1.0-rc1-final上正常运行,Chrome(和其他一些浏览器)和JavaScript应用程序都不会因此类端点而失败。

我想添加的次要功能只是设置StatusCode并关闭响应流以使响应得到满足:

[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!");
        }
    }
}

0
投票

这个问题有点老了,但是我找不到我想做的更好的答案。我发现诀窍是为您要编写的每个内容块打开一个新的StreamWriter。只需执行以下操作:

[HttpDelete]
public void Content()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/html";

    // the easiest way to implement a streaming response, is to simply flush the stream after every write.
    // If you are writing to the stream asynchronously, you will want to use a Synchronized StreamWriter.
    using (var sw = StreamWriter.Synchronized(new StreamWriter(Response.Body)))
    {
        foreach (var item in new int[] { 1, 2, 3, 4, })
        {
            Thread.Sleep(1000);
            sw.Write($"<p>Hi there {item}!</p>");
            sw.Flush();
        }
    };
}

您可以使用以下命令进行卷曲测试:curl -NX DELETE <CONTROLLER_ROUTE>/content


-2
投票

类似的事情可能起作用:

[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);

}
© www.soinside.com 2019 - 2024. All rights reserved.