Превышен предел исключения

Несмотря на то, что MaxRequestLength и maxAllowedContentLength заданы максимально возможные значения в разделе web.config, ASP.Net Core не позволяет загружать файлы, превышающие 134,217,728 Bytes. Точная ошибка, поступающая с веб-сервера:

При обработке запроса произошла необработанная ошибка.

InvalidDataException: превышен предел длины тела 134017728.

Есть ли способ справиться с этим? (ASP.Net Core)

Ответ 1

Я нашел решение этой проблемы после чтения некоторых сообщений в GitHub. Вывод состоит в том, что они должны быть установлены в классе Startup. Например:

public void ConfigureServices(IServiceCollection services)
{
        services.AddMvc();
        services.Configure<FormOptions>(x => {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart
        })
 }

Это решит проблему. Однако они также указали, что существует атрибут [RequestFormSizeLimit], но я еще не смог его установить.

Ответ 2

в случае, если кто-то еще сталкивается с этой проблемой, я создал промежуточное программное обеспечение, которое перехватывает запрос и создает другое тело

    public class FileStreamUploadMiddleware
    {
        private readonly RequestDelegate _next;

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

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.ContentType != null)
            {
                if (context.Request.Headers.Any(x => x.Key == "Content-Disposition"))
                {
                    var v = ContentDispositionHeaderValue.Parse(
                        new StringSegment(context.Request.Headers.First(x => x.Key == "Content-Disposition").Value));
                    if (HasFileContentDisposition(v))
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            context.Request.Body.CopyTo(memoryStream);
                            var length = memoryStream.Length;
                            var formCollection = context.Request.Form =
                                new FormCollection(new Dictionary<string, StringValues>(),
                                    new FormFileCollection()
                                        {new FormFile(memoryStream, 0, length, v.Name.Value, v.FileName.Value)});
                        }
                    }
                }
            }

            await _next.Invoke(context);
        }

        private static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
        {
            // this part of code from  https://github.com/aspnet/Mvc/issues/7019#issuecomment-341626892
            return contentDisposition != null
                   && contentDisposition.DispositionType.Equals("form-data")
                   && (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
                       || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
        }
    }

и в контроллере мы можем получить файлы из запроса

        [HttpPost("/api/file")]
        public IActionResult GetFile([FromServices] IHttpContextAccessor contextAccessor,
            [FromServices] IHostingEnvironment environment)
        {
            //save the file
            var files = Request.Form.Files;
            foreach (var file in files)
            {
                var memoryStream = new MemoryStream();
                file.CopyTo(memoryStream);

                var fileStream = File.Create(
                    $"{environment.WebRootPath}/images/background/{file.FileName}", (int) file.Length,
                    FileOptions.None);
                fileStream.Write(memoryStream.ToArray(), 0, (int) file.Length);

                fileStream.Flush();
                fileStream.Dispose();

                memoryStream.Flush();
                memoryStream.Dispose();
            }

            return Ok();
        }

Вы можете улучшить код для своих нужд, например: добавить параметры формы в тело запроса и десериализовать его.

я думаю, это обходной путь, но он выполняет свою работу.

Ответ 3

В качестве альтернативы используйте атрибут, поэтому эквивалент для действия, разрешенного Transcendant, будет таким:

[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]