在Swagger中为multipart/form-data类型的文件指定内容类型。

10

我已经实现了这个签名的端点。

[HttpPost("Test")]
public IActionResult MyTest([Required] IFormFile pdf, [Required] IFormFile image)
{
    // some stuff...

    return Ok();
}
这会在swagger.json中生成以下条目(相关部分)
"content": {
    "multipart/form-data": {
        "schema": {
            "required": [
                "image",
                "pdf"
            ],
            "type": "object",
            "properties": {
                "pdf": {
                    "type": "string",
                    "format": "binary"
                },
                "image": {
                    "type": "string",
                    "format": "binary"
                }
            }
        },
        "encoding": {
            "pdf": {
                "style": "form"
            },
            "image": {
                "style": "form"
            }
        }
    }
}

但是,我还需要指定编码方式,就像规范(v3)中所述。因此,对于我的任务来说,我认为JSON应该如下所示...

"encoding": {
    "pdf": {
        "style": "form",
        "contentType": "application/pdf"
    },
    "image": {
        "style": "form",
        "contentType": "image/png, image/jpeg"
    }
}
但是我如何从代码中实现呢? 我考虑了 SwaggerParameter 属性,但它只包含描述和必需标志......

我正在使用 .NET Core 2.2 上的 Swashbuckle.AspNetCore NuGet 包 (版本为 5.0.0-rc2)。


1
我也遇到了这个问题! - shertu
2个回答

4

如果您查看此行代码,您会发现编码只使用了Style属性,而没有设置ContentType。您可以通过创建自定义Attribute并定义您的内容类型来手动设置它:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,AllowMultiple = false)]
public class OpenApiEncodingContentTypeAttribute : Attribute
{
    public OpenApiEncodingContentTypeAttribute(string contentType)
    {
        ContentType = contentType;
    }

    public string ContentType { get; }
}

然后在IOperationFilter中使用那个Attribute

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;
                    }
                }
            }
        }
    }
}

然后只需给您的参数加上这个Attribute即可。

[HttpPost("Test")]
public IActionResult MyTest([Required] [OpenApiEncodingContentType("application/pdf")] IFormFile pdf, [Required] [OpenApiEncodingContentType("image/png, image/jpeg")] IFormFile image)
{
    // some stuff...
    return Ok();
}

别忘了在 AddSwaggerGen 中定义你的 IOperationFilter

services.AddSwaggerGen(opts =>
{
    // all other stuff
    opts.OperationFilter<FormContentTypeSchemaOperationFilter>();
})

这是您可以获得的内容。
"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"
        }
      }
    }
  }
}

您可能可以通过添加其他检查/空检查和适合您需求的内容来改进IOperationFilter,因为这只是基本实现。


0

您也可以查看 ISchemaFilter 和以下问题:

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1148

这可能会帮助您为操作筛选并为相同类型(IFormInput)添加不同的contentStyles。

我认为您想要实现的目标目前只能通过自定义属性来实现,但是有一个正在积极开发中的增强FormsInput支持的活动分支,也许您可以添加一个功能请求。

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/commits/enhance-support-for-forms


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接