【问题标题】:API File Upload using HTTP content not exposed in swagger使用未在招摇中公开的 HTTP 内容的 API 文件上传
【发布时间】:2017-07-15 02:35:46
【问题描述】:

我在现有的 Web API 中实现了一个 swagger 接口。当前的 API 控制器公开了一个异步上传功能,该功能使用 Request.Content 异步传输图像。已经使用的代码在this文章中解释。

我的 api 控制器:

    [HttpPost]
    [Route("foo/bar/upload")]
    public async Task<HttpResponseMessage> Upload()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        var provider = await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());
        NameValueCollection formData = provider.FormData;
        HttpResponseMessage response;
        //access files  
        IList<HttpContent> files = provider.Files;
        if (files.Count > 0)
        {
            HttpContent file1 = files[0];
            using (Stream input = await file1.ReadAsStreamAsync())
            {
                object responseObj = ExternalProcessInputStream(input)
                response = Request.CreateResponse(HttpStatusCode.OK, responseObj);
            }
        }
        else 
        {
            response = Request.CreateResponse(HttpStatusCode.BadRequest);
        }
        return response;
    }

这很有效,但是当我通过 swagger 公开它时,我有一个无参数函数,使用时会返回错误。

我的问题是如何提供一个合适的值来测试这个方法?

【问题讨论】:

    标签: c# api swagger


    【解决方案1】:

    您需要添加自定义 IOperationFilter 来处理此问题。

    假设您有这样的控制器:

        [ValidateMimeMultipartContentFilter]
        [HttpPost, Route("softwarepackage")]
        public Task<SoftwarePackageModel> UploadSingleFile()
        {
    
            var streamProvider = new MultipartFormDataStreamProvider(ServerUploadFolder);
            var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<SoftwarePackageModel>(t =>
            {
                var firstFile = streamProvider.FileData.FirstOrDefault();
    
                if (firstFile != null)
                {
                    // Do something with firstFile.LocalFileName
                }
    
                return new SoftwarePackageModel
                {
    
                };
            });
    
            return task;
        }
    

    然后您需要创建一个 Swashbuckle.Swagger.IOperationFilter 以向您的函数添加文件上传参数,例如:

        public class FileOperationFilter : IOperationFilter
        {
            public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
            {
                if (operation.operationId.ToLower() == "softwarepackage_uploadsinglefile")
                {
                    if (operation.parameters == null)
                        operation.parameters = new List<Parameter>(1);
                    else
                        operation.parameters.Clear();
                    operation.parameters.Add(new Parameter
                    {
                        name = "File",
                        @in = "formData",
                        description = "Upload software package",
                        required = true,
                        type = "file"
                    });
                    operation.consumes.Add("application/form-data");
                }
            }
        }
    

    您需要在 Swagger 配置中注册过滤器:

    config.EnableSwagger(c => {... c.OperationFilter<FileOperationFilter>(); ... });
    

    为此,我还添加了一个 FilterAttribute 来过滤掉 Multipart 内容:

    public class ValidateMimeMultipartContentFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (!actionContext.Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }
        }
    
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
    
        }
    
    }
    

    【讨论】:

    • 这是一个非常好的解决方案,对我来说效果很好。但是,如何设置 contentType?
    • 作为您答案的附录,我发现了这个,它做同样的事情,除了它添加了一个属性,您可以用它来装饰您的方法,而不是检查 operationID(我发现这很烦人弄清楚)。 tahirhassan.blogspot.co.il/2017/12/…
    • 对我来说这篇文章也很有帮助。非常相似:talkingdotnet.com/…
    • 为什么使用 application/form-data 作为 mime 类型?我会期待多部分/表单数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 2023-03-11
    • 2019-12-14
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    相关资源
    最近更新 更多