问题描述
我们刚刚将一个Web API项目移植到了.NET5.0 / aspnetcore5和最近的Swashbuckle。目前,表单文件参数未显示在生成的API文档中,并且我们也缺少在Swagger UI中上传文件的功能。
我们有一个简单的文件上传方法,该方法从表单获取名称作为参数和文件内容:
[HttpPut("{fileName:maxlength(255)}",Name = OpIdTemplate]
[HttpPost("{fileName:maxlength(255)}",Name = OpIdTemplate]
[ProducesResponseType(StatusCodes.Status201Created)]
public IActionResult CreateOrUpdate(string fileName)
{
// checks omitted to provide a minimal example
file = Request.Form.Files.Single();
var sanitizedName = _fileHandler.Store(fileName,file);
return CreatedAtRout(Urn,new { fileName = sanitizedFileName },null);
}
当前所需的表单文件未记录在生成的openapi定义中。我们如何才能使swashbuckle包含所需的表单文件?
我们已经尝试使用IFormFile参数
public IActionResult CreateOrUpdate(
[FromRoute] string fileName,[FromBody] List<IFormFile> file)
{
// ...
}
但这会破坏现有的客户端(它们获得415种不受支持的媒体类型)。
很遗憾,您不能再执行此操作,因为OpenApiParameter.In
是ParameterLocation
,仅包含Query
,Header
,Path
和Cookie
可能的值。
public class FileCreateOrUpdateFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation,OperationFilterContext context)
{
var isCreateOrUpdate = true;// for simplicity
if (isCreateOrUpdate)
{
operation.Parameters.Add(new OpenApiParameter
{
Name = "fileContent",In = new ParameterLocation("formData"),// invalid
});
}
}
}
编辑:如果我自己编写Yaml并将其输入到Swagger编辑器中,它将按预期显示文件上传按钮。因此,问题在于使Swashbuckle以某种方式生成content
multipart/form-data:
部分。
post:
description: upload an audio file
- in: path
name: fileName
schema:
type: string
required: true
description: intended name of the file
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
# 'file' will be the field name in this multipart request
file:
type: string
format: binary
responses:
201:
description: return location of created resource (file name may vary from intended name)
因此,在Swashbuckle 5.6.3或更高版本的Request.Form.Files
中使用文件参数时,是否可以添加文件的API文档?那么,要在Swagger UI中启用文件上传,必须做些什么?
解决方法
实际上,我们可以通过显式设置DefaultEntry
来使用IOperationFilter
:
RequestBody
现在有了过滤器,我们需要在public class FileCreateOrUpdateFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation,OperationFilterContext context)
{
var isCreateOrUpdate = true;// for simplicity
if (isCreateOrUpdate)
{
operation.RequestBody = new OpenApiRequestBody
{
Description = "file to upload",Content = new Dictionary<String,OpenApiMediaType>
{
{
"multipart/form-data",new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",Required = new HashSet<String>{ "file" },Properties = new Dictionary<String,OpenApiSchema>
{
{
"file",new OpenApiSchema()
{
// matches our handcrafted yaml
Type = "string",Format = "binary"
}
}
}
}
}
}
}
};
}
}
}
中启用它:
Startup.cs
这应该生成预期的json / yaml输出。生成后,Swagger UI(和Swagger编辑器)将显示文件上传按钮,您可以在此处测试文件上传。