gpt4 book ai didi

asp.net - 已将 'multipart/form-data' 上传到 ASP.NET Web API 操作,在无缓冲模式下不可读

转载 作者:行者123 更新时间:2023-12-02 16:26:25 25 4
gpt4 key购买 nike

我正在构建一个接受“multipart/form-data”请求的 ASP.NET Web API 端点。我按照描述实现它in this article使用 .NET Framework 4.5 和 Web API 2.1。我创建的操作方法的简化版本如下所示:

public async Task<HttpResponseMessage> PostFile()
{
if (!Request.Content.IsMimeMultipartContent()) throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
var rootPath = System.Configuration.ConfigurationManager.AppSettings["StorageLocation"].ToString();
var provider = new MultipartFormDataStreamProvider(rootPath);
var response = Request.CreateResponse(HttpStatusCode.OK);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// Imagine awesome logic here, unicorns and rainbows! Instead of that, we do the following:
response.Content = new StringContent("You uploaded " + provider.FileData.Count.ToString() + " files.");
}
catch (Exception e) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e)); }
return response;
}

由于上传的文件可能非常大(最多 2GiB),我希望我的请求不被 ASP.NET 缓冲,从而避免高内存使用。为了实现这一点,我告诉 Web API 流式传输传入请求,而不是缓冲它们,如 in this article 中所述。 。自定义的WebHostBufferPolicySelector看起来像这样:

public class CustomWebHostBufferPolicySelector : WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
System.Web.HttpContextBase contextBase = hostContext as System.Web.HttpContextBase;
if (contextBase != null && contextBase.Request.ContentType != null && contextBase.Request.ContentType.Contains("multipart")) return false;
else return base.UseBufferedInputStream(hostContext);
}

public override bool UseBufferedOutputStream(System.Net.Http.HttpResponseMessage response)
{
return base.UseBufferedOutputStream(response);
}
}

我在应用程序启动时将这个家伙加载到 Global.asax 中,如下所示:

protected void Application_Start(object sender, EventArgs e)
{
// Here, other stuff got did.
GlobalConfiguration.Configuration.Services.Replace(typeof(IHostBufferPolicySelector), new CustomWebHostBufferPolicySelector());
}

好了,棋盘已经设置好了,让我们开始行动吧。如果我不使用我的CustomWebHostBufferPolicySelector,一切都会正常工作。但是,当使用它时,我得到以下异常:

Message: "An error has occurred."
ExceptionMessage: "Error reading MIME multipart body part."
ExceptionType: "System.IO.IOException"
StackTrace: " at System.Net.Http.HttpContentMultipartExtensions.<ReadAsMultipartAsync>d__0`1.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\ \ at ..."

有以下内部异常:

Message: "An error has occurred."
ExceptionMessage: "Unable to read the entity body in Bufferless mode. The request stream has already been buffered."
ExceptionType: "System.InvalidOperationException"
StackTrace: " at System.Web.Http.WebHost.HttpControllerHandler.<>c__DisplayClass13.<GetStreamContent>b__10()\ \ at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.get_StreamContent()\ \ at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.CreateContentReadStreamAsync()\ \ at System.Net.Http.HttpContent.ReadAsStreamAsync()\ \ at System.Net.Http.HttpContentMultipartExtensions.<ReadAsMultipartAsync>d__0`1.MoveNext()"

看起来请求仍然以某种方式被其他东西缓冲。我应该在 ASP.NET 管道中寻找其他地方吗?或者甚至可能是 IIS?此请求的生命周期中还有哪些地方可以缓冲它,以及如何控制它们?

最佳答案

为了使问题更加清晰并与其他人共享,我创建了一个简单的项目来尝试重现该问题。在这样做的过程中,我找到了答案:禁用所有类型的跟踪。

就我而言,我有 ASP.NET's own tracing functionality已启用,并且还 Glimpse 。这两者都在请求到达 Web API 操作之前缓冲请求。

为了完整起见,这里提供了在测试和生产过程中在 Web.Config 中关闭它们的正确方法。

<configuration>
<system.web>
<trace enabled="false" />
</system.web>
<glimpse defaultRuntimePolicy="Off">
</glimpse>
</configuration>

就我而言,这两个是罪魁祸首,但我可以想象可能还有其他人,所以要小心这一点。

关于asp.net - 已将 'multipart/form-data' 上传到 ASP.NET Web API 操作,在无缓冲模式下不可读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25649114/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com