ASP.NET Core 禁用请求缓冲(不是响应缓冲)

9
我找到了一个关于控制响应缓冲的好方法。但我需要禁用请求缓冲。
问题简述:
我发现后台有一个缓冲区,正在填充请求数据。在请求方法上设置断点并不能暂停此过程,因此很明显是由后台线程完成的。我按照一些说明(例如关闭FormValueProviderFactory)进行操作,但它们并不能阻止这种行为。
问题详述:
我实现了这里的代码。
示例创建了一个名为DisableFormValueModelBindingAttribute的筛选器属性,文档声称可以防止文件被加载到内存中,但它没有这种效果。该筛选器在请求开始流式传输之后才会被触发。
但我发现整个请求仍然被缓存在内存中。它达到了请求内存限制并开始存储在磁盘中,但这导致服务器的磁盘空间不足。由于服务托管在docker中,我只有几百MB可用。我真正需要的是"多部分请求只缓冲到我可以读取它的地方"。
我正在使用AspNetCore 2.1.1的.net core 2.1。
关于Request.EnableBuffering的说明:
名称不正确——请求总是被缓冲的,实际上这只是启用请求倒带。
关于IHttpBufferingFeature.DisableBuffering的说明:
这已经过时了。它没有实现细节。过时标签说:
[Obsolete("See IHttpRequestBodyFeature or IHttpResponseBodyFeature DisableBuffering", error: true)]

但是IHttpRequestBodyFeature 不存在。

令人失望的是,当这个答案出现时,我感到很兴奋!

更多信息

经过一些实验,我已经找出了一些事情。我将请求从控制器中移出,并移到了一个中间件中。

app.Use ((context, next) =>
{

    var Request = context.Request;

    if (MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
    {
        // a breakpoint here doesn't stop the upload
        var path = Request.Path;

// ...

但我发现有一个后台线程在填充请求缓冲区。我在中间件内设置了断点,但我仍然可以看到后台上传过程。请求缓冲区仍在填充。
答案可能与可以对HttpRequestFeature进行的可能配置有关。
进一步的信息
在UseKestrel的回调中,您可以配置限制,其中有一个限制
称为“MaxRequestBufferSize”
但默认情况下为1MB。因此,显然它不负责将完整请求缓冲到磁盘上。
我还发现a github issue关于缓冲可配置,主要是抱怨它没有。这让我感到缺乏信心。
1个回答

1

目前为止,这是不可能的。

IHttpRequestBodyFeature未实现或未公开,因此我们没有可用的方法来调用以禁用请求缓冲。只有一种方法可以使用DisableBuffering方法在IHttpResponseBodyFeature中禁用响应缓冲。

我在GitHub上搜索IHttpRequestBodyFeature,发现了很少的结果https://github.com/search?q=IHttpRequestBodyFeature&type=,这进一步证明了该接口尚未对我们可用或公开。另一方面,如果您搜索IHttpResponseBodyFeature,则会从dotnet和aptnetcore获得大量结果。

我建议提交一个问题,说明IHttpRequestBodyFeature在此处不可用: https://github.com/dotnet/aspnetcore/issues

我无法找到在IHttpResponseFeature中禁用请求缓冲的方法。没有提供method来执行此操作。但是,使用IHttpResponseBodyFeature,有一个method可以禁用响应缓冲;以下是一个示例:

  1. 添加以下命名空间

    using Microsoft.AspNetCore.Http.Features;

  2. 在您想要禁用响应缓冲IActionResults中使用DisableBuffering()方法,该方法:

退出响应的写入缓冲

var bufferingFeature2 = HttpContext.Features.Get<IHttpResponseBodyFeature>();
bufferingFeature2?.DisableBuffering();

1
当你第一次回答时,我真的感到非常兴奋,因为我以为你已经找到了一个简单的解决方案。但是DisableBuffering不再存在。IHttpBufferingFeature接口已经过时(error=true,因此如果您使用它,甚至无法编译),并会指向一个不存在的API。你提供的报价是关于响应的,而不是请求。你已经付出了很多努力,我非常感激,但遗憾的是答案是不正确的。 - speciesUnknown
@gburton,你为什么认为它不再存在了?我重现了过时的错误(在使用IHttpBufferingFeature.DisableBuffering时),但是在使用IHttpResponseBodyFeature.DisableBuffering中修订后的代码中没有出现。 - vvvv4d
1
我刚刚注意到修改后的答案提到了response缓冲区。所以它可能有效,但这是对不同问题的回答!尽管如此,我仍然很感激你所做的工作。希望我能接受这个答案并给你那丰厚的赏金。 - speciesUnknown
1
你的答案似乎是正确的。很遗憾我们实际上无法控制这个缓冲区,所以我将不得不编写一个OWIN中间件来代替。历史上,大文件上传在asp.net中并没有很好地集成,而且在AspnetCore中似乎也不是一个重要的考虑因素。 - speciesUnknown
1
让我们在聊天中继续这个讨论 - speciesUnknown
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接