0

I have ASP.NET Core WebApi application and need to upload very large file. I have enabled JWT Auth/Authz

services.AddAuthentication(cfg =>
{
     cfg.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
     cfg.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, cfg =>
{ .. }

TTL of token is 2 minutes.

Then I have action in my controller like

public async Task<IActionResult> Add(IFormFile file)
{
     if (file.Length.ToMegabytes() > 500)
     {
        throw new BadRequestException(nameof(file), "File size should not exceed 500 MB");
     }
}

and config in web host

.UseKestrel(options =>
 {
    options.Limits.MaxRequestBodySize = null;
 })

When I upload a large file (~1Gb) it is take a long time and then returns 401 before it step into my action.

How can I check that file has not valid size before it will be uploaded? Because uploading take a time more than 2 minutes and in a result I will get 401

Я TChebur
  • 366
  • 6
  • 23
  • Possible duplicate of [Asp.Net Check file size before upload](https://stackoverflow.com/questions/3094748/asp-net-check-file-size-before-upload) – layonez Oct 18 '19 at 15:07
  • It is not a duplicate, because I asked abiut asp.net core webapi but not for asp.net and jquery – Я TChebur Oct 18 '19 at 15:14
  • afaik you can't do a proper check before file upload, because you'll need to upload the file in order for the server to know how big the file is. – Sasha Oct 18 '19 at 15:16
  • but my token will be expire before all checks. how can I handle it without changes lifetime of token – Я TChebur Oct 18 '19 at 15:20
  • I think main idea is not changed between any type of framework or lang, you should try to do that check first on client side – layonez Oct 18 '19 at 15:29
  • I do not have a client side, I have web api – Я TChebur Oct 18 '19 at 15:39

1 Answers1

2

The problem is that when modelbinding a file upload, the entire file contents have to be spooled to the server before the action can be invoked. However, particularly if you're uploading large files, you should not be modelbinding the upload, but rather, streaming it. This should have the side effect of getting around your authorization problem, as well, because the action will be invoked immediately.

The docs describe exactly how to stream large file uploads. It's not trivial, but this is how you should do it, regardless, for the best app performance and stability.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • thanks, it make sense. can I use streaming but leave param `IFormFile file` in my action? – Я TChebur Oct 18 '19 at 15:33
  • No. You have to manually parse the request body, as the documentation indicates. This is essentially what the modelbinder is doing, except in that case, it must finish streaming the file *before* it can bind the `IFormFile` param. This is because an action with a param cannot be invoked until the modelbinder has provided a value for that param. – Chris Pratt Oct 18 '19 at 15:36
  • So it means that I can't use Swagger anymore to upload file, right? is there any way to use swagger for streaming? – Я TChebur Oct 18 '19 at 15:41
  • That's actually interesting. I hadn't considered the implications of this with something that actually *relies* on the method being self-documenting, like Swagger. *Theoretically*, if you add the attribute that disables modelbinding, I suppose you could keep the param; it just would have no value, so it would be a little confusing from a code perspective. – Chris Pratt Oct 18 '19 at 16:08
  • There *may* be a way to kind of trick out Swashbuckle/NSwag to tell it to offer an upload field without literally having a param. You'd have to check the respective documentation. – Chris Pratt Oct 18 '19 at 16:10