Превышен предел исключения
Несмотря на то, что 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)]