Reputation: 5755
Although having set the MaxRequestLength
and maxAllowedContentLength
to the maximum possible values in the web.config
section, ASP.Net Core does not allow me to upload files larger than 134,217,728 Bytes
. The exact error coming from the web server is:
An unhandled exception occurred while processing the request.
InvalidDataException: Multipart body length limit 134217728 exceeded.
Is there any way to work this around? (ASP.Net Core)
Upvotes: 77
Views: 54632
Reputation: 86
Solution for Minimal API
To configure just one endpoint (which is preferable), here's the code you'll need.
app.MapPost("/upload", (IFormFile file) =>
{
// ...
})
.WithFormOptions(multipartBodyLengthLimit: 2_000_000_000L);
Upvotes: 0
Reputation: 31950
If you use int.MaxValue
(2,147,483,647) for the value of MultipartBodyLengthLimit
as suggested in other answers, you'll be allowing file uploads of approx. 2Gb, which could quickly fill up disk space on a server. I recommend instead setting a constant to limit file uploads to a more sensible value e.g. in Startup.cs
using MyNamespace.Constants;
public void ConfigureServices(IServiceCollection services)
{
... other stuff
services.Configure<FormOptions>(options => {
options.MultipartBodyLengthLimit = Files.MaxFileUploadSizeKiloBytes;
})
}
And in a separate constants class:
namespace MyNamespace.Constants
{
public static class Files
{
public const int MaxFileUploadSizeKiloBytes = 250000000; // max length for body of any file uploaded
}
}
Upvotes: 3
Reputation: 571
Alternatively use the attribute, so the equivalent for an action as resolved by Transcendant would be:
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
Upvotes: 34
Reputation: 560
in case some one still face this problem i've created a middle-ware which intercept the request and create another body
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));
}
}
and in the controller we can fetch the files form the request
[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();
}
you can improve the code for your needs eg: add form parameters in the body of the request and deserialize it.
its a workaround i guess but it gets the work done.
Upvotes: 1
Reputation: 5755
I found the solution for this problem after reading some posts in GitHub. Conclusion is that they have to be set in the Startup
class. For example:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<FormOptions>(x => {
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart
})
}
This will solve the problem. However they also indicated that there is a [RequestFormSizeLimit]
attribute, but I have been unable to reference it yet.
Upvotes: 163