如何在 ASP.NET 响应中将 Transfer-Encoding 设置为显式或隐式分块?

Posted

技术标签:

【中文标题】如何在 ASP.NET 响应中将 Transfer-Encoding 设置为显式或隐式分块?【英文标题】:How can I set Transfer-Encoding to chunked, explicitly or implicitly, in an ASP.NET response? 【发布时间】:2011-02-05 10:20:54 【问题描述】:

我可以简单地设置Transfer-Encoding 标头吗?

在某些时候调用Response.Flush() 会导致这种情况隐式发生吗?


编辑 不,我不能打电话给Response.Headers.Add("Transfer-Encoding","anything"); 那会抛出。

还有其他建议吗?


相关:Enable Chunked Transfer Encoding in ASP.NET

【问题讨论】:

在 Java Servlet 中,如果你 not 在写入/刷新流之前设置 Content-Length 标头,它将被隐式设置为 Transfer-Encoding: chunked 并且数据将是分块发送。查看 ASP.NET 中是否存在类似行为。 在 ASPNET 中,它会隐式缓存输出,我认为。 HttpResponse 上有一个 BufferOutput 属性。但是,该物业上的文件是完全不足的。 msdn.microsoft.com/en-us/library/… 它没有说明该属性如何影响 Transfer-Encoding 或任何其他有趣的问题。 【参考方案1】:

Response.Buffer = 假

这将设置 HTTP Header "Tranfer-Encoding:Chuncked" 并发送每个调用 response.write 的响应

【讨论】:

【参考方案2】:

TL;DR: 指定内容长度是实现快速首字节的最佳方式;您将允许在 TCP 而不是 HTTP 级别进行分块。如果您不知道内容长度,将context.Response.BufferOutput 设置为false 将在使用分块传输编码写入输出流时发送输出。


为什么要设置Transfer-Encoding: chunked?分块传输本质上是一种解决方法,允许发送内容长度事先不知道的文档。然而,ASP.NET 默认缓冲整个输出,因此确实知道整个内容的长度。

当然,HTTP 是在 TCP 之上分层的,并且在幕后 TCP 无论如何都会通过将单个 HTTP 响应拆分为数据包来“分块”——这意味着如果你预先指定内容长度并禁用输出缓冲,你'将获得最佳延迟 不需要 HTTP 级别的分块。 因此,当您知道内容长度时,您不需要 HTTP 级别的分块来提供快速的第一个字节。

虽然我不是 HTTP 方面的专家,但我已经实现了一个简单的流媒体服务器,它具有寻求支持、动态压缩、缓存等功能,并且我对快速第一个字节的相关性有一个合理的把握——而分块是如果你知道内容长度通常是一个较差的选项 - 这几乎肯定是 ASP.NET 不允许你手动设置它的原因 - 它只是没有必要。

但是,如果您在传输之前不知道 HTTP 内容长度并且缓冲太昂贵,则关闭输出缓冲,并且推测服务器将根据需要使用分块传输编码。 p>

服务器什么时候使用分块传输编码?我刚刚测试过,确实context.Response.BufferOutput设置为false,而当内容长度不是设置,响应被分块;在我对 1.7MB 内容编码:gzip xml 文档的完全非科学快速测试中,这样的响应要大 1-2%。由于 gzip 依赖于上下文来减少冗余,我预计压缩率会受到更多影响,但似乎分块并不一定会大大降低压缩率。

如果您查看反射器中的框架代码,似乎传输编码确实是根据需要自动设置的 - 即,如果缓冲关闭并且不知道内容长度并且响应是对 HTTP/1.1 请求的响应,则分块传输使用编码。但是,如果服务器是 IIS7 并且这是一个工作请求(?集成模式?),代码会分支到本地方法 - 可能具有相同的行为,但我无法验证。

【讨论】:

@Eamon,分块传输不是一种解决方法,它们是一项功能。我想你知道这一点,但是当内容的大小未知并且在写入第一个响应字节时可能很大,那么它是不正确的,有潜在的危险,并且如果 ASPNET 尝试缓存整个发送之前的响应。关于 BufferOutput 的使用 - 你能引用你“刚刚检查”的来源吗?你的意思是你测试过?我也观察到了这种行为。我正在寻找的是有据可查的描述。 Response.Flush() 能做到吗?等 我观察到了。如果查看反射器中的代码,关闭缓冲区输出实际上相当于在每次写入后调用刷新;并且每个非最终刷新检查并设置分块传输编码,如果标题尚未写入,尚未被抑制,客户端未断开连接,这不是“最终”刷新,响应的内容长度为'不要手动设置,并且 http 版本是 1.1 - 需要注意的是有一些代码会检查 IIS7 并为此执行其他操作,这看起来更复杂。 无论如何,关键是如果您担心缓冲过大的响应 - 关闭缓冲;不要明确担心分块传输编码(这只是在禁用缓冲并且服务器无法推断内容长度时发送响应的机制)。您不需要手动启用分块传输编码,据我所知 - 没有理由。 @Eamon - 您似乎认为应用程序永远不应该关心是否发生缓冲或分块传输。但事实并非如此。假设要传输的数据很大,并且大小是已知的。假设应用程序知道响应将是 1gb。应用程序明确确保不发生缓冲是有意义的,这意味着分块编码。你似乎忽略了这种可能性。或者考虑第一个字节的时间,分块传输比没有传输时更小。举两个例子。关键是,有充分的理由明确使用 HTTP 的这一特性。 不,这不是真的 - 应用程序可能关心它是否被缓冲 - 但分块传输编码只是一种应用程序可以“无缓冲”的方式。如果您明确设置内容长度并关闭缓冲,您仍然不会进行分块传输,但 具有低延迟 - 事实上,它会比分块传输编码稍快,因为总响应大小会更小。所以,我并不是说应用程序不应该关心无缓冲,我是说应用程序不应该关心 如何 实现无缓冲 - 分块传输编码 not 需要低延迟!【参考方案3】:

虽然您将 Buffer 设置为 false 并将内容长度留空,但您需要确保您已禁用 IIS7 的“动态内容压缩”功能以使分块响应正常工作。此外,客户端浏览器应至少具有 HTTP 1.1 .. 分块模式不适用于 HTTP 1.0

【讨论】:

【参考方案4】:

看来您需要为此设置 IIS。 IIS 6 在元数据库中有一个属性 AspEnableChunkedEncoding,您可以在 MSDN 上的 http://msdn.microsoft.com/en-us/library/aa965021(VS.90).aspx 上查看 IIS 7 映射。 这将使您能够在标题中设置 TRANSFER-ENCODING: 分块。我希望这会有所帮助。

【讨论】:

谢谢。但是 AspEnableChunkedEncoding 默认为 true,所以这不是问题。此外,这并没有回答有关在 ASPNET 中使用分块编码的具体问题。

以上是关于如何在 ASP.NET 响应中将 Transfer-Encoding 设置为显式或隐式分块?的主要内容,如果未能解决你的问题,请参考以下文章

如何在.net 2.0中将数据从数据库或DataTable保存到Excel文件而没有响应

ASP.NET Core 中 Server.Transfer 的替代方案

HTTPServerUtility.Transfer 是不是比 Response.Redirect 在 asp.net 中的网站性能更有用?

如何在 asp .NET 中将记录添加到数据库中

在 ASP.NET Core 应用程序中将 HTTPS 站点重定向到非 www

如何在编辑模式 ASP .Net 中将日期选择器放在 Gridview 中