REST .NET Core 2.2〜为什么会出现异常“超出了多部分主体的长度限制16384。”?

时间:2019-05-28 10:45:19

标签: c# .net rest asp.net-core .net-core

我有一个 .NET Core 2.2 API 和一个 POST ,用于通过上传大量的文件

我得到了例外 “超出了多部分身体长度限制16384。”

例外出现在行...

section = await reader.ReadNextSectionAsync();

...在FileStreamHelper.cs中(见下文)。

我使用邮递员尝试上传。我的文件有10 MB。 当选择 Body / binary 时,会出现此异常。 当我选择 Body / form-data 时,出现异常“ Stream意外结束,内容可能已被另一个组件读取。”。但是我没有通过其他组件或之前读取文件。 我猜二进制应该正确。对吗?

在我的Startup.cs中定义

        services.Configure<FormOptions>(options =>
        {
            options.MemoryBufferThreshold = Int32.MaxValue;
            options.ValueCountLimit = 10; //default 1024
            options.ValueLengthLimit = int.MaxValue; //not recommended value
            options.MultipartBodyLengthLimit = long.MaxValue; //not recommended value
        });

我也在Startup.cs上使用

            app.UseWhen(context => context.Request.Path.StartsWithSegments("/File"),
            appBuilder =>
            {
                appBuilder.Run(async context =>
                {
                    context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = (long)( 2 * System.Math.Pow( 1024, 3 )); // = 2GB 
                    await Task.CompletedTask;
                });
            });

在Program.cs中,我使用

            .UseKestrel(options =>
            {
                options.Limits.MaxRequestBodySize = (long)(2 * System.Math.Pow(1024, 3)); // = 2 GB
            })

在我的控制器上,我使用属性 [DisableRequestSizeLimit]

此异常的原因可能是什么?

如何解决此问题?

所有代码: 控制器

[Route("api/v1/dataPicker/fileUploadStream")]
public class FileStreamUploadController : ControllerBase
{
    [HttpPost]
    [DisableRequestSizeLimit]
    [DisableFormValueModelBinding]
    public async Task<IActionResult> Upload()
    {
        var streamer = new FileStreamingHelper();
        var paths = "c:\\temp\\";
        var tempName = Guid.NewGuid().ToString("N");
        using
            (
            var stream = System.IO.File.Create($"{paths}tempName")
            )
            await streamer.StreamFile(Request, stream);
        string from = $"{paths}tempName";
        string to = $"{paths}{streamer.FileNames.FirstOrDefault() ?? tempName}";
        System.IO.File.Move(from, to);
        return Ok($"Uploaded File {paths}{streamer.FileNames.FirstOrDefault() ?? tempName}");
    }
}

FileStreamHelper

    public async Task<FormValueProvider> StreamFile(HttpRequest request, Stream targetStream)
    {
        if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
        {
            throw new Exception($"Expected a multipart request, but got {request.ContentType}");
        }

        var formAccumulator = new KeyValueAccumulator();

        var boundary = MultipartRequestHelper.GetBoundary(
            MediaTypeHeaderValue.Parse(request.ContentType),
            _defaultFormOptions.MultipartBoundaryLengthLimit);
        var reader = new MultipartReader(boundary, request.Body);

        MultipartSection section;
        try
        {
            section = await reader.ReadNextSectionAsync();
        }
        catch (Exception ex)
        {
            throw;
        }
        while (section != null) ...}

    public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
    {
        var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary);
        if (StringSegment.IsNullOrEmpty(boundary))
        {
            throw new InvalidDataException("Missing content-type boundary.");
        }

        if (boundary.Length > lengthLimit)
        {
            throw new InvalidDataException(
                $"Multipart boundary length limit {lengthLimit} exceeded.");
        }

        return boundary.Value;
    }

您需要更多代码才能看到?请告诉我!

这里是邮递员标题... enter image description here

邮递员的身体... enter image description here

2 个答案:

答案 0 :(得分:0)

请尝试通过首先解析内容类型的方式来检索边界:

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

 var reader = new MultipartReader(boundary.Value, request.Body);

 //Rest of the code

另外,请附上您的邮递员请求的屏幕截图,尤其是邮件头

答案 1 :(得分:0)

我不得不对邮递员进行不同的配置。 enter image description here

1)正文/表单数据

2)在“密钥”下,用鼠标输入该字段,然后下拉并选择“文件”

3)在“值”下方单击新按钮,然后选择一个文件

4)在字段“ KEY”中写上“ File”一词

那不容易发现。 ;-) 所有Header数据并不重要。 现在可以了。