REST .NET Core 2.2 ~ Зачем получать исключение «Превышен предел длины тела, состоящий из 16384 частей»? - PullRequest
0 голосов
/ 28 мая 2019

У меня есть .NET Core 2.2 API с POST для загрузки большого файла через stream .

Я получаю исключение "Превышен предел длины тела, состоящий из нескольких частей, 16384."

Исключение появляется в строке ...

section = await reader.ReadNextSectionAsync();

... в FileStreamHelper.cs (см. Ниже).

Я использую почтальон, чтобы попробовать загрузить.Мой файл имеет 10 МБ.Я получаю это исключение, когда выбираю Body / binary .Когда я выбираю Body / form-data , вместо этого я получаю исключение «Неожиданный конец потока, возможно, содержимое уже прочитано другим компонентом».Но я не читал файл другим компонентом или раньше. Я думаю, двоичный файл должен быть правильным. Правильно?

В моем файле 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 голосов
/ 28 мая 2019

Мне пришлось настроить почтальона по-другому .. enter image description here

1) Тело / форма-данные

2) под «КЛЮЧ» введите поле мышью, затем выпадающий и выберите «Файл»

3) ниже значения нажмите на новую кнопку и выберите файл

4) напишите в поле «КЛЮЧ» слово «Файл»

Это было нелегко выяснить. ;-) Все данные заголовка не были важны. Теперь это работает.

0 голосов
/ 28 мая 2019

Пожалуйста, попробуйте получить границу таким образом, предварительно проанализировав тип контента:

 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

Также, пожалуйста, приложите скриншот вашего запроса почтальона, особенно заголовки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...