7

我正在使用 Nancy 编写一个简单的 Web 应用程序。至少一个请求会导致未知长度的流,所以我无法提供Content-Length. 我想使用Transfer-Encoding: chunked, 或(在这种情况下同样可以接受,Connection: close)。

我对 Nancy 源代码进行了快速破解,并且添加Response.BufferOutput了 , 和代码以设置HttpContext.Response.BufferOutputfalse. 你可以在这里看到:

public class HomeModule : NancyModule
{
    public HomeModule()
    {
        Get["/slow"] = _ => new SlowStreamResponse();
    }

    private class SlowStreamResponse : Response
    {
        public SlowStreamResponse()
        {
            ContentType = "text/plain";
            BufferOutput = false;
            Contents = s => {
                byte[] bytes = Encoding.UTF8.GetBytes("Hello World\n");
                for (int i = 0; i < 10; ++i)
                {
                    s.Write(bytes, 0, bytes.Length);
                    Thread.Sleep(500);
                }
            };
        }
    }

它似乎没有任何效果。5 秒后立即出现响应。我已经测试了这个基于简单WebRequest的客户端。

如何让分块输出在 Nancy 中工作?我正在使用 ASP.NET 托管,但我会对其他托管选项的答案感兴趣。

如果我使用 编写一个简单的服务器HttpListener,我可以设置SendChunkedtrue,它会发送分块输出,我的简单客户端会正确接收分块输出。

4

3 回答 3

6

在我的实验过程中,我发现我需要以下配置。首先,按照Nancy Wiki中的说明设置您的web.config文件。值得注意的是,为了设置该值(这是我们想要的),您目前似乎还需要指定一个引导程序。在您的程序集中创建一个继承自配置文件并在配置文件中指定它的类似乎可行。disableoutputbufferNancy.Hosting.Aspnet.DefaultNancyAspNetBootstrapper

<configSections>
  <section name="nancyFx" type="Nancy.Hosting.Aspnet.NancyFxSection" />
</configSections>
<nancyFx>
  <bootstrapper assembly="YourAssembly" type="YourBootstrapper"/>
  <disableoutputbuffer value="true" />
</nancyFx>

之后,您不应该设置Transfer-Encoding标题。相反,以下路由定义似乎正确地将结果从我的 IIS Express 开发服务器流式传输到 Chrome:

Get["/chunked"] = _ =>
{
  var response = new Response();
  response.ContentType = "text/plain";
  response.Contents = s =>
  {
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes("Hello World ");
    for (int i = 0; i < 10; ++i)
    {
      for (var j = 0; j < 86; j++)
      {
        s.Write(bytes, 0, bytes.Length);
      }
      s.WriteByte(10);
      s.Flush();
      System.Threading.Thread.Sleep(500);
    }
  };

  return response;
};

由于其他StackOverflow 问题中记录的第一次渲染之前的最小尺寸,我为每个块指定了​​比上一个示例更多的内容

于 2016-06-14T19:20:08.123 回答
4

You have to call Flush() after each Write(), otherwise the response is buffered anyway. Moreover, Google Chrome doesn't render the output until it's all received.

I discovered this by writing a simple client application that logged what it was reading from the response stream as it arrived.

于 2012-07-14T18:44:24.753 回答
0

如果使用 .NET 4.5+,您也可以使用 Stream.CopyTo 而不是刷新。

Get["/chunked"] = _ =>
{
  var response = new Response();
  response.ContentType = "text/plain";
  response.Contents = s =>
  {
    using(var helloStream = new MemoryStream(Encoding.UTF8.GetBytes("Hello World ")))
      helloStream.CopyTo(s);
  }
  return response;
}
于 2018-02-26T14:37:52.090 回答