Unexpected end of Stream, the content may have already been read by another component.

See original GitHub issue

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:

https://stackoverflow.com/questions/49867343/unexpected-end-of-stream-the-content-may-have-already-been-read-by-another-comp

But if there was problem with lack of DisableFormValueModelBinding then wouldn’t every upload request fail this way?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:56 (22 by maintainers)

github_iconTop GitHub Comments

2reactions
spaasiscommented, Aug 26, 2020

I ran into this as well, using the fetch() API on the browser.

First, I POST a form to the current page:

let response = await fetch(url, {
        method: 'post',
        body: data,
    });

The matching controller (this same endpoint is used without issues when posting forms normally via a submit button):

 public async Task<IActionResult> OnPost() {
            //functionality
            return RedirectToPage("");
        }

This results in a HTTP 302 response, as it should. However, fetch() will follow the redirect path but it still appends the Content-Type to the next GET headers:

Host: localhost:44337
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: */*
Accept-Language: fi,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------18467633426500 **THIS CAUSES THE EXCEPTION**
Origin: https://localhost:44337
Referer: https://localhost:44337/Inspection/Transportation/11
Connection: keep-alive
Cookie: ...
TE: Trailers

If I resend the GET without the Content-Type, everything works as it should.

It seems that the Content-Type should be straight up ignored in GET requests, as it should be irrelevant? At least it should result in a 400 instead of 500. Although I think it’s also a bug that fetch() sends that invalid header in the first place.

EDIT: I solved the issue by adding a custom header to the fetch call, and then returning 200 directly if the call came from fetch

2reactions
davidfowlcommented, May 11, 2020

Thanks I can reproduce the issue now!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unexpected end of Stream, the content may have already ...
I get an exception when I try to read multi part content from the request saying the content may have already been read...
Read more >
Unexpected end of Stream when uploading to aspnet core
One of those has shown up when trying to POST a file. ... ":"Unexpected end of Stream, the content may have already been...
Read more >
Flurl multipart/form-data Unexpected End of Stream
IO.IOException: Unexpected end of Stream, the content may have already been read by another component.". TLDR. The root cause of this error ...
Read more >
Unexpected end of Stream, the content may have already ...
I get an exception when I try to read multi part content from the request saying the content may have already been read...
Read more >
uploading image using multipart/form - Postman Works
IOException: Unexpected end of Stream, the content may have already been read by another component. Microsoft.AspNetCore.WebUtilities.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found