Как включить документацию и загрузку файлов для параметра formData в Swashbuckle 5.6.3 для OpenApi 3?

Мы только что портировали проект веб-API на ASP.NET Core 5.0 и недавнюю версию Swashbuckle. В настоящее время параметр файла формы не отображается в сгенерированной документации API, и нам также не хватает возможности загрузить файл в пользовательском интерфейсе Swagger.

У нас есть простой метод загрузки файла, который получает имя в качестве параметра и содержимое файла из формы:

[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. Как мы можем заставить автомат включить этот требуемый файл формы?

Мы уже пробовали использовать параметр IFormFile

public IActionResult CreateOrUpdate(
    [FromRoute] string fileName,
    [FromBody] List<IFormFile> file)
{
    // ...
}

но это нарушает работу существующих клиентов (они получают 415 неподдерживаемых типов носителей).

Раньше можно было расширить swashbuckle с настраиваемым IOperationFilter добавлением Parameter с In = "formData".

К сожалению, вы больше не можете этого делать, поскольку 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)

Так есть ли способ добавить документацию API к параметру файла при его использовании из Request.Form.Files в Swashbuckle 5.6.3 или новее? Что же тогда нужно сделать, чтобы разрешить загрузку файлов в пользовательском интерфейсе Swagger?


person mbx    schedule 12.11.2020    source источник


Ответы (1)


Мы действительно можем сделать это с 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:

services.AddSwaggerGen(c =>
{
    
    // ...

    c.OperationFilter<FileCreateOrUpdateFilter>();
}

Это должно сгенерировать ожидаемый вывод json / yaml. Как только это будет сгенерировано, пользовательский интерфейс Swagger (и редактор Swagger) покажет кнопку загрузки файла, и вы сможете протестировать загрузку файла прямо здесь.

person mbx    schedule 13.11.2020