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
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:
///
/// 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; }
}
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"
}
}
}
}
});
}
}
services.AddSwaggerGen(options =>
{
...
options.OperationFilter();
}
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");
}