Handling file uploads in OpenAPI

asp.net webapi webapp sql

This post is about implementing handling file uploads in OpenAPI with ASP.NET Core. Open API is one way to document REST API endpoints. When we using Web API and IFormFile class to upload a file, OpenAPI will display a File Upload control in the UI like this.

Also, I recommend to read my other post Uploading files in ASPNET Core if you have to upload big file.

Minimal API

So, with NET6, Microsoft introduced minimal APIs: the core idea behind minimal APIs is to remove some of the ceremony of creating simple APIs. It means defining lambda expressions for individual API calls. Now, this is an example for an upload method to upload a file via the API with Swagger.

app.MapPost("/upload", async (IFormFile file) =>
{
    //Do something with the file
    return Results.Ok();
}).Accepts<IFormFile>("multipart/form-data").Produces(200);

Which will render something like this.

File Upload in Open API

Earlier versions of Open API won’t render it properly. And if we are using multiple IFormFile elements this won’t work properly. Here is an example.

app.MapPost("/upload-multiple", async (IFormFile[] files) =>
{
    //Do something with the files
    return Results.Ok();
}).Accepts<IFormFile[]>("multipart/form-data").Produces(200);

Which will result something like this.

Multiple File Upload in Open API

And if we not using IFormFile and using Request.Form object to receive file upload then also it will not render properly. We can fix this by introducing a custom OperationFilter implementation.

The implementation

So, here is the code to manage multiple files.

public class FileUploadOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var fileUploadMime = "multipart/form-data";
        if (operation.RequestBody == null ||
            !operation.RequestBody.Content.Any(x => 
            x.Key.Equals(fileUploadMime, StringComparison.InvariantCultureIgnoreCase)))
        {
            return;
        }
        var name = context.ApiDescription.ActionDescriptor.DisplayName;
        operation.Parameters.Clear();
        if (context.ApiDescription.ParameterDescriptions[0].Type != typeof(IFormFile))
        {
            var uploadFileMediaType = new OpenApiMediaType()
            {
                Schema = new OpenApiSchema()
                {
                    Type = "object",
                    Properties =
                {
                    ["files"] = new OpenApiSchema()
                    {
                        Type = "array",
                        Items = new OpenApiSchema()
                        {
                            Type = "string",
                            Format = "binary"
                        }
                    }
                },
                    Required = new HashSet<string>() { "files" }
                }
            };

            operation.RequestBody = new OpenApiRequestBody
            {
                Content = { ["multipart/form-data"] = uploadFileMediaType }
            };
        }
    }
}

And we can include this in the UI like this.

builder.Services.AddSwaggerGen(setup =>
{
    setup.OperationFilter<FileUploadOperationFilter>();
}

Which will render something like this – clicking on Add string item button will add File Upload controls.

Multiple File Upload in Open API
Post request in Swagger

We can modify the FileUploadOperationFilter code and use the same code if you’re using Request.Form to accept files in the server side.

Wrap up

In conclusion, this is how handling file uploads in OpenAPI. Please leave your comment in our forum.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.