ASP.NET Core cookbook · Intermediate

Accept file uploads with size and type limits

Uploads can fill the disk, overwrite files or carry the wrong content.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Accept IFormFile, enforce request size limits, check the extension and the file signature, save under a generated name outside the web root (or in blob storage), and return the new resource's ID.

Solution

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/api/documents", async (IFormFile file, CancellationToken ct) =>
{
    if (file.Length is 0 or > 10 * 1024 * 1024)
        return Results.Problem("File must be between 1 byte and 10 MB.", statusCode: 400);
    if (!string.Equals(Path.GetExtension(file.FileName), ".pdf", StringComparison.OrdinalIgnoreCase))
        return Results.Problem("Only PDF files are accepted.", statusCode: 400);

    await using var stream = file.OpenReadStream();
    var header = new byte[5];
    await stream.ReadExactlyAsync(header, ct);
    if (!header.AsSpan().SequenceEqual("%PDF-"u8))
        return Results.Problem("The file isn't a valid PDF.", statusCode: 400);
    stream.Position = 0;

    var id = Guid.NewGuid();
    var path = Path.Combine("/var/app-data/documents", $"{id:N}.pdf");    // outside wwwroot
    await using var target = File.Create(path);
    await stream.CopyToAsync(target, ct);
    return Results.Created($"/api/documents/{id}", new { id });
})
.DisableAntiforgery()                                   // API called with bearer tokens, not cookies
.WithMetadata(new Microsoft.AspNetCore.Mvc.RequestSizeLimitAttribute(11 * 1024 * 1024));
app.Run();

Pitfalls

  • Using file.FileName in the storage path (path traversal, overwrites).
  • Buffering huge uploads in memory; stream them or upload directly to blob storage with SAS URLs.
  • Disabling antiforgery for cookie-authenticated form posts.

Variations

  • For large files, stream multipart sections with MultipartReader instead of model binding.
  • Scan files with an antivirus service before making them available.

Further reading: Upload files

Reference: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads

More ASP.NET Core recipes

Was this page helpful?