CoreUpload vs IFormFile
Every other comparison here is with a JavaScript library. This one is with the framework itself — because for most ASP.NET Core teams the real alternative is not Uppy, it is an IFormFile parameter and a CopyToAsync.
IFormFile is the right tool for a profile picture or a CSV import. It is built in, it is three lines, and it costs nothing. It is a server-side abstraction over a normal multipart form post, and it is complete on that side.
What it does not include is the browser half. There is no progress, no chunking, no resume, no drop target and no client-side validation, because none of those are server concerns. CoreUpload is that browser half plus the endpoints it talks to. If you do not need the browser half, you do not need CoreUpload.
The whole interface is eight members: ContentType, ContentDisposition, Headers, Length, Name, FileName, CopyToAsync and OpenReadStream. A minimal-API upload is genuinely this short:
app.MapPost("/upload", async (IFormFile file) =>
{
await using var stream = File.Create(Path.Combine("uploads", Path.GetRandomFileName()));
await file.CopyToAsync(stream);
return Results.Ok();
}).DisableAntiforgery();Note Path.GetRandomFileName() rather than file.FileName. That is not a stylistic choice: the ASP.NET Core documentation warns not to use FileName for anything but display and logging, and to HTML-encode it even then.
| Limit | Default | What happens |
|---|---|---|
Kestrel MaxRequestBodySize | 30,000,000 bytes (~28.6 MB) | 413, or BadHttpRequestException. |
MultipartBodyLengthLimit | 134,217,728 bytes (128 MB) | InvalidDataException when the section is parsed. |
MemoryBufferThreshold | 64 KB | Anything larger is spooled to a temporary file on disk before your handler runs. |
That third row is the one that surprises people. Model binding buffers the upload — in memory below 64 KB, otherwise to a temp file under ASPNETCORE_TEMP — so by the time your code sees the IFormFile, the transfer is already finished and already on the disk. Streaming with MultipartReader avoids the buffering, and the documentation is candid that it "doesn't improve performance significantly"; it reduces memory and disk pressure, not transfer time.
The full chain of limits, including IIS and reverse proxies, is on Uploading large files.
| IFormFile | CoreUpload | |
|---|---|---|
| Scope | Server side only | Browser component + endpoints |
| Transfer | One multipart post | single, chunked, tus, or direct to S3 / Azure / GCS |
| Progress | Not applicable | Per-file and overall, with speed and ETA |
| Interrupted upload | Starts over | Resumes from the last completed chunk |
| Validation | After the bytes arrive | In the browser first, re-checked on arrival |
| Blazor | Hand-written interop | <CoreUploader /> component |
| Cost | In the framework | Commercial licence |
CoreUpload does not replace IFormFile — its own default endpoint receives the file the same way. It replaces everything that has to happen before the request is made.