Sunil Buddala
Sunil Buddala

Reputation: 1241

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

I get an exception when I try to read multi part content from the request saying the content may have already been read by another component.

 if (MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                // Used to accumulate all the form url encoded key value pairs in the 
                // request.
                var formAccumulator = new KeyValueAccumulator();

                var boundary = Request.GetMultipartBoundary();
                var reader = new MultipartReader(boundary, HttpContext.Request.Body);
                var section = await reader.ReadNextSectionAsync();
                while (section != null)
                {
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader =
                        ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
                }
            }

Upvotes: 22

Views: 40102

Answers (15)

Brian Yule
Brian Yule

Reputation: 49

In addition to disabling form value model binding, I had to update the anti-forgery middleware to stop generating the token when using file upload, by leveraging the Http request "Endpoint Feature".

public async Task InvokeAsync(HttpContext context)

{

    var endpoint = context.Features?.Get<Microsoft.AspNetCore.Http.Features.IEndpointFeature>();

    if (context.User?.Identity != null &&

        context.User.Identity.IsAuthenticated &&

        endpoint?.Endpoint?.Metadata.GetMetadata<DisableFormValueModelBindingAttribute>() == null)

    {

        var tokenSet = antiforgery.GetAndStoreTokens(context);

        var requestToken = tokenSet.RequestToken;



        if (requestToken != null)

        {

            context.Response.Cookies.Append(

                "XSRF-TOKEN",

                requestToken,

                new () { HttpOnly = false, Path = "/", Secure = true, SameSite = SameSiteMode.Strict, });

        }

    }



    await next(context);

}

Upvotes: 0

Salman Arshad
Salman Arshad

Reputation: 272236

In my case the issue was the payload... the Content-Length of the request was different from the actual length of the payload. The JavaScript code that was creating the HTTP POST was fixed to get rid of this issue.

Background: The original code looked similar to the Next.js code in this question except that it also included a Content-Length header that was different from the length of the body. And it was because the body was corrupted by body parser function. The solution is in that question.

Upvotes: 0

Cheikh faye Ndiaye
Cheikh faye Ndiaye

Reputation: 1

In my case I forgot IResourceFilter in DisableFormValueModelBindingAttribute. work fine in .Net7

Upvotes: 0

irhetoric
irhetoric

Reputation: 361

In my case, I had to remove the [ValidateAntiForgeryToken] attribute.

Upvotes: 1

Glebka
Glebka

Reputation: 1668

I have this error when send invalid form-data from client. This is valid format: NOTE: two minuses and new line in the end

<empty>
------------------------------8dac95867d24bd1
Content-Disposition: form-data; name="user_login"

<data or empty>
------------------------------8dac95867d24bd1
Content-Disposition: form-data; name="user_password"

<data or empty>
------------------------------8dac95867d24bd1
Content-Disposition: form-data; name="user_session"

<data or empty>
------------------------------8dac95867d24bd1--
<empty>

Upvotes: 1

johnstaveley
johnstaveley

Reputation: 1499

In my case I had added another filter which was intercepting the file. Even with the filters mentioned above I still got the issue. Removing the honey pot removed the error finally.

            .AddMvc(options =>
            {
                options.Filters.Add(new AuthorizeFilter());
                // .... etc
                options.AddHoneyPot(); // This was causing the problem
            })

Upvotes: 1

Jordy
Jordy

Reputation: 101

If you are using MultipartFormDataContent to send the file, at the other side you will receive a mediaTypeHeader.Boundary.Value with an escaped " at the start & end (eg "\"BoundaryValue\"").

So by removing it, it started working for me. The fix for me was to add this at receiver side: .Replace("\"", "")

mediaTypeHeader.Boundary.Value.Replace("\"", "")

Upvotes: 0

Devi99
Devi99

Reputation: 11

Just in case someone else is chasing ghosts regarding this error: using net5 web api I had a controller with

    [HttpPost]
    [Route("api/fileupload/{reportId}")]
    [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
    public async Task<IActionResult> FileUpload(int reportId)

That wasn't a good idea. It gave the abovementionned error and I remembered having to pass on additional data via file attributes. That solved it for me. Just for completeness. This worked off course

    [HttpPost]
    [Route("api/fileupload")]
    [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
    public async Task<IActionResult> FileUpload()

Upvotes: 1

diant
diant

Reputation: 51

This worked for me for netcore 3.1

You need to add

factories.RemoveType<FormFileValueProviderFactory>();

on this method

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        var factories = context.ValueProviderFactories;
        factories.RemoveType<FormValueProviderFactory>();
        factories.RemoveType<FormFileValueProviderFactory>();
        factories.RemoveType<JQueryFormValueProviderFactory>();
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

Upvotes: 5

Rae
Rae

Reputation: 605

In my specific case, I was using a multipart boundary value which didn't exist in the payload being parsed by the MultipartReader:

// multipartBoundary is not in the contents of httpResponseContentStream.
var multipartBoundary = "batchresponse_63d0e4c7-4d49-4961-a294-3902d1730c44";
var multipartReader = new MultipartReader(multipartBoundary, httpResponseContentStream);
// Unexpected end-of-stream error used to occur here:
var multipartSection = await multipartReader.ReadNextSectionAsync(cancellationToken);

Once the multipartBoundary was updated to reflect an actual boundary value present in the content being parsed, the code worked as expected.

Upvotes: 7

Learner
Learner

Reputation: 2649

In asp.net core 3, You have to add factories.RemoveType<FormFileValueProviderFactory>(); to your DisableFormValueModelBindingAttribute attribute.

Code

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        var factories = context.ValueProviderFactories;
        factories.RemoveType<FormValueProviderFactory>();
        factories.RemoveType<FormFileValueProviderFactory>();
        factories.RemoveType<JQueryFormValueProviderFactory>();
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

Documentation

Upvotes: 39

aleha_84
aleha_84

Reputation: 8539

In my case it was "postman" issue. I sent the file to the REST endpoint. And at some point I started to get this error, but the code was not changed.

I re-selected this file again in "postman" and everything worked as before.

Upvotes: 0

Iren Saltalı
Iren Saltalı

Reputation: 536

There is bug about that in Microsoft.AspNetCore.App 2.1.4. I updated this package to 2.1.12 version and it resolved.

Upvotes: 0

Random Lyrics
Random Lyrics

Reputation: 45

I used [DisableFormValueModelBinding] but still got error, then i also use:

if (Request.ContentLength == 0)
                return BadRequest();

Upvotes: 2

Sunil Buddala
Sunil Buddala

Reputation: 1241

It turns out that I had to disable form value model binding by using the attribute below.

[HttpPost]
    [Route("")]
    [DisableFormValueModelBinding]
    public async Task<IActionResult> Post()

The attribute implementation is below

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        var factories = context.ValueProviderFactories;
        factories.RemoveType<FormValueProviderFactory>();
        factories.RemoveType<JQueryFormValueProviderFactory>();
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

Upvotes: 24

Related Questions