Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

I met a mistake:Multipart body length limit 16384 exceeded #7019

Closed
ynanech opened this issue Nov 2, 2017 · 12 comments
Closed

I met a mistake:Multipart body length limit 16384 exceeded #7019

ynanech opened this issue Nov 2, 2017 · 12 comments
Milestone

Comments

@ynanech
Copy link

ynanech commented Nov 2, 2017

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

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

        services.AddMvc();
    }
@Eilon
Copy link
Member

Eilon commented Nov 2, 2017

@Tratcher any idea on this limit?

@Tratcher
Copy link
Member

Tratcher commented Nov 2, 2017

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.

@Eilon
Copy link
Member

Eilon commented Nov 2, 2017

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

@ynanech
Copy link
Author

ynanech commented Nov 3, 2017

@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

@Tratcher
Copy link
Member

Tratcher commented Nov 3, 2017

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.

@ynanech
Copy link
Author

ynanech commented Nov 3, 2017

@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

@Tratcher
Copy link
Member

Tratcher commented Nov 3, 2017

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

@ynanech
Copy link
Author

ynanech commented Nov 3, 2017

@Tratcher
Is this one?
4_Full.txt

@Tratcher
Copy link
Member

Tratcher commented Nov 3, 2017

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);

@Tratcher Tratcher removed their assignment Nov 3, 2017
@Tratcher Tratcher added this to the Discussions milestone Nov 3, 2017
@ynanech
Copy link
Author

ynanech commented Nov 5, 2017

@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(Please 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

}`

@Tornhoof
Copy link

Tornhoof commented Nov 6, 2017

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

@ynanech
Copy link
Author

ynanech commented Nov 7, 2017

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

@ynanech ynanech closed this as completed Nov 7, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants