Mastering File Uploads and Downloads in .NET 8 Minimal APIs: A Comprehensive Guide

leandroveiga

Leandro Veiga

Posted on October 27, 2024

Mastering File Uploads and Downloads in .NET 8 Minimal APIs: A Comprehensive Guide

File uploads and downloads are essential features for many applications. Whether you’re handling document uploads, image downloads, or large file exchanges, .NET 8 Minimal APIs provide an efficient way to manage file transfers seamlessly. In this guide, I'll show you exactly how to handle file uploads and downloads in Minimal APIs with a focus on simplicity, security, and scalability.

Let’s dive in and explore how to make your Minimal API file-ready in no time!


Why Handle File Uploads and Downloads in Minimal APIs?

Adding file upload and download capabilities enhances your API by:

  • Supporting user uploads like documents, photos, and videos.
  • Enabling data exchange for files that clients need to access, modify, or archive.
  • Improving UX by enabling secure and efficient file handling directly within your API.

Minimal APIs, known for their lightweight and straightforward design, are an excellent choice for building file transfer functionality into modern applications without complex overhead.


1. Setting Up a Minimal API Project for File Handling

To get started, let’s create a .NET 8 Minimal API project. Open your terminal and run:

dotnet new web -n FileUploadDownloadDemo
cd FileUploadDownloadDemo
Enter fullscreen mode Exit fullscreen mode

Open Program.cs, where we’ll define the endpoints for file uploads and downloads.


2. Handling File Uploads in Minimal APIs

In Minimal APIs, handling file uploads is simple using IFormFile. This allows you to access the file data as it’s uploaded and process it accordingly.

Step 1: Creating the File Upload Endpoint

Let’s create an endpoint to accept file uploads. Add the following code in Program.cs:

app.MapPost("/upload", async (IFormFile file) =>
{
    if (file.Length > 0)
    {
        var filePath = Path.Combine("Uploads", file.FileName);

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        return Results.Ok(new { FilePath = filePath });
    }
    return Results.BadRequest("Invalid file.");
});
Enter fullscreen mode Exit fullscreen mode

This code saves the uploaded file to a folder named Uploads. If the file is successfully saved, it returns the file path; otherwise, it responds with a BadRequest.

Step 2: Configuring File Storage

Make sure to create the Uploads directory in your project root. You can configure file storage by setting permissions and paths in your application’s configuration, ensuring that sensitive data is handled securely.


3. Handling File Downloads in Minimal APIs

File downloads are straightforward in Minimal APIs. We’ll create an endpoint that serves a file when requested, making it accessible to clients for download.

Step 1: Creating the File Download Endpoint

Add the following code in Program.cs to enable file downloads:

app.MapGet("/download/{fileName}", (string fileName) =>
{
    var filePath = Path.Combine("Uploads", fileName);

    if (!File.Exists(filePath))
    {
        return Results.NotFound("File not found.");
    }

    var fileBytes = File.ReadAllBytes(filePath);
    return Results.File(fileBytes, "application/octet-stream", fileName);
});
Enter fullscreen mode Exit fullscreen mode

This endpoint looks for the requested file in the Uploads folder. If found, it returns the file with an appropriate MIME type (application/octet-stream for generic binary data), which triggers a download prompt in most browsers.


4. Best Practices for Secure and Efficient File Handling

When handling file uploads and downloads, there are several best practices to keep in mind for security and performance:

a. Limit File Sizes

To prevent large files from overloading your server, set a maximum file size limit. You can configure this in your application’s settings:

builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 10 * 1024 * 1024; // 10 MB
});
Enter fullscreen mode Exit fullscreen mode

b. Validate File Types

Restricting file types can help prevent malicious files from being uploaded. Here’s an example of basic file validation:

if (!file.ContentType.StartsWith("image/"))
{
    return Results.BadRequest("Only image files are allowed.");
}
Enter fullscreen mode Exit fullscreen mode

c. Store Files Securely

Store files in directories with limited permissions and avoid placing them in public directories to prevent unauthorized access. You may also consider storing files in a cloud storage solution like Azure Blob Storage or AWS S3 for better scalability.

d. Use Streaming for Large Files

For large files, use streaming to avoid memory issues. This is especially useful for file downloads where loading the entire file into memory is inefficient.

Example of a download with streaming:

app.MapGet("/download-stream/{fileName}", async (string fileName, HttpContext httpContext) =>
{
    var filePath = Path.Combine("Uploads", fileName);

    if (!File.Exists(filePath))
    {
        return Results.NotFound("File not found.");
    }

    httpContext.Response.ContentType = "application/octet-stream";
    httpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{fileName}\"");

    await using var stream = new FileStream(filePath, FileMode.Open);
    await stream.CopyToAsync(httpContext.Response.Body);
});
Enter fullscreen mode Exit fullscreen mode

This approach sends the file in chunks, reducing memory usage.


5. Testing File Uploads and Downloads

Testing file upload and download functionality is crucial. Here’s a basic example using Postman:

  1. File Upload:

    • Set the HTTP method to POST and enter the URL: http://localhost:5000/upload.
    • In the Body tab, select form-data, enter file as the key, and upload a sample file.
  2. File Download:

    • Set the HTTP method to GET and enter the URL: http://localhost:5000/download/yourfile.jpg.
    • Send the request, and you should receive the file as a downloadable response.

Automate these tests where possible to ensure your file handling logic is robust and consistent.


6. Extending File Uploads and Downloads with Authentication

For most applications, file access should be restricted to authorized users. Here’s a basic example of securing these endpoints with JWT authentication:

app.MapPost("/upload", [Authorize] async (IFormFile file) =>
{
    // File upload logic here
});

app.MapGet("/download/{fileName}", [Authorize] (string fileName) =>
{
    // File download logic here
});
Enter fullscreen mode Exit fullscreen mode

With [Authorize], only authenticated users can access the file upload and download endpoints. You’ll need to configure authentication in your Minimal API project and ensure clients provide a valid JWT.


7. Handling File Uploads and Downloads in the Cloud

For scalability, consider using cloud storage providers like Azure Blob Storage or AWS S3. Here’s a quick example of how to upload a file to Azure Blob Storage:

builder.Services.AddSingleton(x =>
{
    var blobServiceClient = new BlobServiceClient("YourAzureBlobStorageConnectionString");
    return blobServiceClient.GetBlobContainerClient("uploads");
});

app.MapPost("/upload", async (IFormFile file, BlobContainerClient containerClient) =>
{
    var blobClient = containerClient.GetBlobClient(file.FileName);

    using var stream = file.OpenReadStream();
    await blobClient.UploadAsync(stream, true);

    return Results.Ok($"File uploaded to {blobClient.Uri}");
});
Enter fullscreen mode Exit fullscreen mode

This code uploads the file to an Azure Blob Storage container, and you can retrieve it using the blob’s URI. Cloud storage provides secure, scalable storage ideal for large or frequently accessed files.


Conclusion

With Minimal APIs in .NET 8, handling file uploads and downloads is efficient and flexible. By following best practices for security, scalability, and performance, you can build robust file handling capabilities into your APIs.

This guide covered:

  • Setting up upload and download endpoints in Minimal APIs.
  • Securing file uploads with size limits, type validation, and authentication.
  • Streaming large files to reduce memory usage.
  • Using cloud storage solutions for scalable file handling.

Whether you’re building a simple file-sharing feature or integrating with cloud storage, .NET 8 Minimal APIs make it easy to manage files reliably.


By mastering these techniques, you’ll be equipped to add efficient file handling to any .NET API, ensuring your application is responsive, secure, and scalable.

💖 💪 🙅 🚩
leandroveiga
Leandro Veiga

Posted on October 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related