zoukankan      html  css  js  c++  java
  • 使用Swagger直接上传文件的方法

    经常使用swagger,可以通过设置[ProducesResponseType]标记接口的返回信息;swagger也能通过接口的参数列表,自动获得发送的数据结构信息。

    不过有一个例外,就是上传文件的时候,设置了[Consumes]的内容为multi-part/form-data,但是swagger并不能正常感知是上传文件的。代码是这个样子的:

    关于文件上传的细节,可以看多年前我写过一篇有关通过WEBAPI上传文件的文章

    [Consumes("multipart/form-data")]
    [ODataRoute]
    [HttpPost]
    public async Task<ActionResult> Post(IFormCollection collection)
    {
        var file = collection.Files[0];
        if(file != null)
        {
            var filename = DateTime.Now.ToString("yyyyMMddHHmmss") + file.FileName;
            var path = Path.Combine(_webHostEnvironment.WebRootPath, "Files", filename);
            using FileStream fileStream = new FileStream(path, FileMode.Create);
            await file.CopyToAsync(fileStream);
            var uri = "Files/" + filename;
            var fileEntity = new Models.File { Url = uri, LastModified = DateTime.Now };
            _homeworkDataContext.Files.Add(fileEntity);
            await _homeworkDataContext.SaveChangesAsync();
            return Created(WebUtility.UrlEncode(uri), fileEntity);
        }
        return BadRequest();
    }
    

    实际上,swagger一直提示,上传的内容是一个array类型,当然API是没有问题的,可以通过POSTMAN进行发送,不过不能在网页上直接操作,总觉得心里有点不太舒服。

    方法

    搜索了一下办法,比较靠谱的,就是通过增加一个IOperationFilter来实现目的。

    // CODE FROM https://www.talkingdotnet.com/how-to-upload-file-via-swagger-in-asp-net-core-web-api/
    public class FileUploadOperation : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            if (operation.OperationId.ToLower() == "apivaluesuploadpost")
            {
                operation.Parameters.Clear();
                operation.Parameters.Add(new NonBodyParameter
                {
                    Name = "uploadedFile",
                    In = "formData",
                    Description = "Upload File",
                    Required = true,
                    Type = "file"
                });
                operation.Consumes.Add("multipart/form-data");
            }
        }
    }
    

    然后,在services.ConfigureSwaggerGen()参数中,添加

    options.OperationFilter<FileUploadOperation>(); 
    

    方法的原理是通过重写操作某个特定API的的过滤器,来实现对返回内容的操作。

    此方法适用于OAS2,实质上是实现了这里的规范要求。

    我已经用上.NET 5.0了,自带了swagger都支持的是OpenAPI 3,这个方法不好用了。不过思想应该相同,首先看看OpenAPI 3的规范,文件上传需要定义为:

    requestBody:
      content:
        multipart/form-data:
          schema:
            type: object
            properties:
              fileName:
                type: string
                format: binary
    

    这个套路和OpenAPI 2完全不一样,需要重新设置requestBody才行。我们按照要求改造代码。

    public class FileUploadOperation : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            //判断上传文件的类型,只有上传的类型是IFormCollection的才进行重写。
            if (context.ApiDescription.ActionDescriptor.Parameters.Any(w => w.ParameterType == typeof(IFormCollection)))
            {
                Dictionary<string, OpenApiSchema> schema = new Dictionary<string, OpenApiSchema>();
                schema["fileName"] = new OpenApiSchema { Description = "Select file", Type = "string", Format = "binary" };
                Dictionary<string, OpenApiMediaType> content = new Dictionary<string, OpenApiMediaType>();
                content["multipart/form-data"] = new OpenApiMediaType { Schema = new OpenApiSchema { Type = "object", Properties = schema } };
                operation.RequestBody = new OpenApiRequestBody() { Content = content };
            }
        }
    }
    

    执行之后,swagger已经可以正常识别了,通过选择文件即可上传,效果如下:

    参考资料

  • 相关阅读:
    redis在centos7下安装(源码编译)
    Centos7之Gcc安装
    Jmeter工具之上传图片,上传音频文件接口
    什么是系统平均负载(Load average)
    sonar+Jenkins 构建代码质量自动化分析平台
    数据库主从相关配置参数说明
    现有数据库配置主从同步
    MySQL5.7多主一从(多源复制)同步配置
    MySQL5.7主从从配置
    MySQL5.7主从同步配置
  • 原文地址:https://www.cnblogs.com/podolski/p/14213210.html
Copyright © 2011-2022 走看看