-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
I have some weird problem which happens to only 1 user of let's say 50
When he uploads file there's Unexpected end of Stream, the content may have already been read by another component. at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool1 bytePool, Nullable1 limit, CancellationToken cancellationToken) at Microsoft.AspNetCore.WebUtilities.MultipartReader.ReadNextSectionAsync(CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken) at Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context) at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList1 factories) at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()
` being thrown
Here's my endpoint:
[HttpPost]
public async Task<JsonResult> UploadFile(IFormFile file, int type, string otherParam)
The thing is that I have middleware which logs every request, so it is reading requests and setting body position to 0 in order to be able to use request data later
public async Task Invoke(HttpContext ctx)
{
var request = await FormatRequest(ctx.Request, ctx);
Log.Information(request);
await next(ctx);
}
private async Task<string> FormatRequest(HttpRequest request, HttpContext ctx)
{
//This line allows us to set the reader for the request back at the beginning of its stream.
request.EnableRewind();
//We now need to read the request stream. First, we create a new byte[] with the same length as the request stream...
var length = Convert.ToInt32(request.ContentLength);
if (length > 30000)
return $"file of length: {length}";
var buffer = new byte[length];
//...Then we copy the entire request stream into the new buffer.
await request.Body.ReadAsync(buffer, 0, buffer.Length);
//We convert the byte[] into a string using UTF8 encoding...
var bodyAsText = Encoding.UTF8.GetString(buffer);
//..and finally, assign the read body back to the request body, which is allowed because of // EnableRewind()
request.Body.Position = 0;
return $"User: '{ctx?.User?.Identity?.Name}' {Environment.NewLine} {request.Scheme} {request.Host}{request.Path} {Environment.NewLine} {request.QueryString} {Environment.NewLine} {bodyAsText}";
}
I thought that early return in
if (length > 30000)
return $"file of length: {length}";
may cause problems, but when file's too large, then I'm receiving Request body too large.
I Increased
.UseKestrel(x =>
{
x.Limits.MaxRequestBodySize = 100_000_000;
})
and now I'm able to upload "huge files" fine, so that
if (length > 30000)
return $"file of length: {length}";
isn't causing this problem, but original problem Unexpected end of Stream, the content may have already been read by another component. still probably remains.
Anybody has an idea what may go wrong? or how to debug that?
I'm unable to reproduce it on any (dev/prod/beta) environment., but I see this exception in logs. It only occurs when that user uploads file. AFAIK he's using Chrome.
.NET Core 2.1
We're posting those files via JS.
I've seen that solution:
But if there was problem with lack of DisableFormValueModelBinding then wouldn't every upload request fail this way?