簡體   English   中英

為 Swagger 的 multipart/form-data 中的文件指定內容類型

[英]Specify content-type for files in multipart/form-data for Swagger

我已經用這個簽名實現了端點

[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)。

如果您查看這一行,您將看到僅使用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 ,因為這只是一個基本實現。

您還可以查看 ISchemaFilter 和以下問題:

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

這可能會幫助您過濾操作並為相同類型 (IFormInput) 添加不同的 contentStyles。

我相信您想要實現的目標目前只能通過自定義屬性實現,但是在活動開發中存在用於增強 FormsInput 支持的活動分支,也許您可​​以添加功能請求。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM