Specify content-type for files in multipart/form-data for Swagger
If you look at this line, you'll see that encoding is created with only Style
property, while ContentType
is not set. What you can do is set this manually by creating custom Attribute
where you'd define your content type:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,AllowMultiple = false)]
public class OpenApiEncodingContentTypeAttribute : Attribute
{
public OpenApiEncodingContentTypeAttribute(string contentType)
{
ContentType = contentType;
}
public string ContentType { get; }
}
and then use that Attribute
within IOperationFilter
public class FormContentTypeSchemaOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var contentTypeByParameterName = context.MethodInfo.GetParameters()
.Where(p => p.IsDefined(typeof(OpenApiEncodingContentTypeAttribute), true))
.ToDictionary(p => p.Name, s => s.GetCustomAttribute<OpenApiEncodingContentTypeAttribute>().ContentType);
if (contentTypeByParameterName.Any())
{
foreach (var requestContent in operation.RequestBody.Content)
{
var encodings = requestContent.Value.Encoding;
foreach (var encoding in encodings)
{
if (contentTypeByParameterName.TryGetValue(encoding.Key, out string value))
{
encoding.Value.ContentType = value;
}
}
}
}
}
}
Then just decorate your parameters with this Attribute
[HttpPost("Test")]
public IActionResult MyTest([Required] [OpenApiEncodingContentType("application/pdf")] IFormFile pdf, [Required] [OpenApiEncodingContentType("image/png, image/jpeg")] IFormFile image)
{
// some stuff...
return Ok();
}
Also don't forget to define your IOperationFilter
in AddSwaggerGen
services.AddSwaggerGen(opts =>
{
// all other stuff
opts.OperationFilter<FormContentTypeSchemaOperationFilter>();
})
This is what you get
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"required": [
"image",
"pdf"
],
"type": "object",
"properties": {
"pdf": {
"type": "string",
"format": "binary"
},
"image": {
"type": "string",
"format": "binary"
}
}
},
"encoding": {
"pdf": {
"contentType": "application/pdf",
"style": "form"
},
"image": {
"contentType": "image/png, image/jpeg",
"style": "form"
}
}
}
}
}
You can probably improve IOperationFilter
with additional checks/null-checks and other stuff that suits your needs, because this is just a basic implementation.