What is the correct way to download a file via the NSwag Code Generator (angular 2 typescript)

后端 未结 4 1790
盖世英雄少女心
盖世英雄少女心 2021-02-13 16:50

I try to download a file via an angular 2 typescript client. The link generated in Swagger UI works fine, but the generated typescript client does not.

The controller lo

4条回答
  •  失恋的感觉
    2021-02-13 17:52

    Eric Gontier's solution works great for Swashbuckle 4 and NSwag 12. If you've upgraded to swashbuckle 5 and thus OpenApi 3 and NSwag 13, then the solution is different. Instead you'll need a custom operation filter, and an reusable attribute to indicate the content-type result:

    Custom attribute

    /// 
    /// Indicates swashbuckle should expose the result of the method as a file in open api (see https://swagger.io/docs/specification/describing-responses/)
    /// 
    [AttributeUsage(AttributeTargets.Method)]
    public class FileResultContentTypeAttribute : Attribute
    {
        public FileResultContentTypeAttribute(string contentType)
        {
            ContentType = contentType;
        }
    
        /// 
        /// Content type of the file e.g. image/png
        /// 
        public string ContentType { get; }
    }
    

    Operation filter

    public class FileResultContentTypeOperationFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var requestAttribute = context.MethodInfo.GetCustomAttributes(typeof(FileResultContentTypeAttribute), false)
                .Cast()
                .FirstOrDefault();
    
            if (requestAttribute == null) return;
    
            operation.Responses.Clear();
            operation.Responses.Add("200", new OpenApiResponse
            {
                Content = new Dictionary
                {
                    {
                        requestAttribute.ContentType, new OpenApiMediaType
                        {
                            Schema = new OpenApiSchema
                            {
                                Type = "string",
                                Format = "binary"
                            }
                        }
                    }
                }
            });
        }
    }
    

    Startup.cs

    services.AddSwaggerGen(options =>
    {
        ...
        options.OperationFilter();
    }
    

    Sample Controller

    Then annotate your controller with the attribute.

    [HttpPost]
    [Route("{fileName}.csv")]
    [FileResultContentType("text/csv")]
    public async Task Generate(string fileName, [FromBody]MyDto myDto)
    {
        var fileMemoryStream = GetCsvAsBytes(myDto);
        return File(fileMemoryStream,
            "text/csv", fileName + ".csv");
    }
    

提交回复
热议问题