Mvc: I met a mistake锛歁ultipart body length limit 16384 exceeded

Created on 2 Nov 2017  路  12Comments  路  Source: aspnet/Mvc

I use the middle to achieve large file upload, but encountered a mistake, I should be how to solve?

0
1
2

_All of the settings below are invalid_

```c#
public void ConfigureServices(IServiceCollection services)
{
services.Configure(x =>
{
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = int.MaxValue;
x.MultipartHeadersLengthLimit = int.MaxValue;
});

    services.AddMvc();
}

```

All 12 comments

@Tratcher any idea on this limit?

Some multipart bodies include preamble data before the first mutipart section. MultipartReader automatically drains that portion but limits it to 16k. There's not currently a way to configure this behavior.
See https://github.com/aspnet/HttpAbstractions/blob/c0f937239a0a099b73c67c96ab9e1c875952f67f/src/Microsoft.AspNetCore.WebUtilities/MultipartReader.cs#L48-L50

Do you know why your upload includes a large preamble section? This is likely unintentional.

@Tratcher parking this on your plate until we can figure out what's wrong.

@Tratcher @Eilon
Thank you for your help.
I want to adjust the limit, but the setting is invalid, I want to achieve a separate file upload service through the middleware, I test only upload a 31.7KB file, it is temporarily unable to achieve this idea, I refer to this tutorial:
https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming

What client are you using for the upload? An HTML form in a browser? Which browser?

Can you share a Fiddler trace of the upload? From your description it contains unexpected content.

@Tratcher
I use Postman to upload, and this is the fiddler content
5

This is the test code:
`
public class FileStreamUploadMiddleware
{
private readonly RequestDelegate _next;

    public FileStreamUploadMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        var boundary = HeaderUtilities.RemoveQuotes(context.Request.ContentType);
        var reader = new MultipartReader(boundary.Value, context.Request.Body);
        reader.HeadersLengthLimit = int.MaxValue;
        var section = await reader.ReadNextSectionAsync();
        while (section != null)
        {
            ContentDispositionHeaderValue contentDisposition;
            var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

            if (hasContentDispositionHeader)
            {
                if (HasFileContentDisposition(contentDisposition))
                {
                    //淇濆瓨鏂囦欢
                }
            }
            section = await reader.ReadNextSectionAsync();
        }
    }

    #region Helper
    public static bool IsMultipartContentType(string contentType)
    {
        return !string.IsNullOrEmpty(contentType)
               && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
    }
    public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
    {
        // Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
        return contentDisposition != null
               && contentDisposition.DispositionType.Equals("form-data")
               && (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
                   || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
    }
    #endregion
}

`
6

Can you save and upload that Fiddler trace? I need to see the request body.

@Tratcher
Is this one?
4_Full.txt

The request looks normal, but I see you're retrieving the boundary incorrectly.
var boundary = HeaderUtilities.RemoveQuotes(context.Request.ContentType);
The linked sample code does this instead:

    var boundary = MultipartRequestHelper.GetBoundary(
        MediaTypeHeaderValue.Parse(Request.ContentType),
        _defaultFormOptions.MultipartBoundaryLengthLimit);

@Eilon @Tratcher
Feedback problem is too tired, I hope you can run the test code(FileStreamUploadMiddleware) I provided above, you will find the core issues. Can you take a look at it?

My code and the core of the official code is the same!
var boundary = HeaderUtilities.RemoveQuotes(context.Request.ContentType);
The following is an example of the official code:
qq 20171105183210

Please run the test code I provided, you will find the problem, I modified the size limit, but still use the default settings.
cccccccc84335

Test code锛圥lease run it锛夛細

`public class FileStreamUploadMiddleware
{
private readonly RequestDelegate _next;

public FileStreamUploadMiddleware(RequestDelegate next)
{
    _next = next;
}

public async Task Invoke(HttpContext context)
{
    var boundary = HeaderUtilities.RemoveQuotes(context.Request.ContentType);
    var reader = new MultipartReader(boundary.Value, context.Request.Body);
    reader.HeadersLengthLimit = int.MaxValue;
    var section = await reader.ReadNextSectionAsync();
    while (section != null)
    {
        ContentDispositionHeaderValue contentDisposition;
        var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

        if (hasContentDispositionHeader)
        {
            if (HasFileContentDisposition(contentDisposition))
            {
                //淇濆瓨鏂囦欢
            }
        }
        section = await reader.ReadNextSectionAsync();
    }
}

#region Helper
public static bool IsMultipartContentType(string contentType)
{
    return !string.IsNullOrEmpty(contentType)
           && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}
public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
{
    // Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
    return contentDisposition != null
           && contentDisposition.DispositionType.Equals("form-data")
           && (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
               || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
}
#endregion

}`

What @Tratcher is referring to:
You use:
var boundary = HeaderUtilities.RemoveQuotes(context.Request.ContentType);
context.Request.ContentType is in your request multipart/form-data; boundary=----WebKitFormBoundary8Su1nBMUX1qEXx1z, you need to first parse it, because you're only interested in the boundary parameter

In the reference code you posted, contentType is already a parsed MediaTypeHeaderValue, take a close look at your screenshot it says contentType.Boundary, and take a look at the method signature it says MediaTypeHeaderValue, so yes you need to do exactly what @Tratcher said, parse the content-Type to MediaTypeHeaderValue then take the property Boundary and strip the (optional) quotes.
e.g.

var parsedContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType);
var boundary = HeaderUtilities.RemoveQuotes(parsedContentType.Boundary);

You can also use the extension method GetMultipartBoundary from Microsoft.AspNetCore.Http.Extensions, see: https://github.com/aspnet/HttpAbstractions/blob/dev/src/Microsoft.AspNetCore.Http.Extensions/HttpRequestMultipartExtensions.cs

I am sorry, I ignored this small detail, thank you very much for the patience solution. thank

Was this page helpful?
0 / 5 - 0 ratings