Возврат файлового потока с помощью SwashBuckle

Я хочу вернуть файловый поток с помощью SwashBuckle

    [System.Web.Http.HttpGet]
    [System.Web.Http.Route("Files/{uid}/file")]
    [SwaggerResponse(HttpStatusCode.OK, Type = typeof(Byte[]))]
    public HttpResponseMessage DownloadFile(String uid, String fileName)
    {
        return Safe.Execute(() =>
        {
            var api = new FileApi();
            var stream = api.GetFile(uid, fileName);

            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
            result.Content = new StreamContent(stream);
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            result.Content.Headers.ContentDisposition =
                     new ContentDispositionHeaderValue("attachment")
                     {
                         FileName = CalcFileName(fileName)
                     };
            return result;
        });
    }

И вижу, что файл возвращен, но... как-то... закодирован. Файл длиной 3798 становится размером 5789 байт после загрузки через пользовательский интерфейс, и содержимое файла очень похоже на ожидаемое, но включены дополнительные байты, как если бы он интерпретировался как строка и стал версией в кодировке UTF-8.

Ничего не меняется, когда я заменяю его как:

    [SwaggerResponse(HttpStatusCode.OK, Type = typeof(Stream))]

Сгенерированный Swagger дескриптор выглядит так:

        "produces": [    
          "application/json",    
          "text/json",    
          "application/xml",    
          "text/xml"    
        ],    
        ...
        "responses": {    
          "200": {    
            "description": "OK",    
            "schema": {    
              "format": "byte",    
              "type": "string"
        }

Любая идея, как реализовать возврат файлового потока из метода контроллера?


person Zoltan Hernyak    schedule 10.05.2018    source источник
comment
Файловый поток создается как System.IO.File.OpenRead(fileName)   -  person Zoltan Hernyak    schedule 10.05.2018
comment
Почему Accept: application/octet-stream не отображается в пользовательском интерфейсе Swagger? Интересно, хорошо ли это работает, кроме как из пользовательского интерфейса?!   -  person Zoltan Hernyak    schedule 10.05.2018
comment
Возможно, поможет рабочий пример: swagger- net-test.azurewebsites.net/swagger/ui/   -  person Helder Sepulveda    schedule 10.05.2018
comment
... И код моего примера находится здесь: github.com/heldersepu/Swagger-Net-Test/blob/master/Swagger_Test/   -  person Helder Sepulveda    schedule 10.05.2018
comment
Атрибут [SwaggerResponse(200, Download a image, mediaType: application/octet-stream)] теперь нельзя применить, mediaType неизвестен. Здесь допустим только параметр Type. Может ли ваш код использовать более старую версию SwashBuckle?   -  person Zoltan Hernyak    schedule 11.05.2018
comment
Ооо, ваш код использует другую библиотеку. используя Swagger.Net.Annotations; - мой использует Swashbuckle.Swagger.Annotations; ...   -  person Zoltan Hernyak    schedule 11.05.2018
comment
Мне кажется, что ошибка в интерфейсе SwashBuckle. Когда я использую curl напрямую, файл загружается хорошо. Через пользовательский интерфейс SwashBuckle файл плохой. :( Интересно, как я могу хорошо описать метод API для пользовательского интерфейса.   -  person Zoltan Hernyak    schedule 11.05.2018


Ответы (1)


Чтобы описать метод API, вы можете использовать IOperationFilter в своей конфигурации swagger.

public class UpdateFileDownloadOperations : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry s, ApiDescription a)
    {
        if (operation.operationId == "DownloadFile_Get")
        {
            operation.produces = new[] { "application/octet-stream" };
        }
    }
}

Если вы никогда не использовали фильтры, загляните на страницу проекта: https://github.com/domaindrivendev/Swashbuckle/blob/e0053e1864defa3c4f73ca2a960eb876e257cc9e/Swashbuckle.Dummy.Core/App_Start/SwaggerConfig.cs


В примере с моим комментарием я использую Swagger-Net очень похоже , но я сделал некоторые улучшения, и, возможно, вы заметили, что он использует последнюю версию пользовательского интерфейса Swagger.

person Helder Sepulveda    schedule 11.05.2018
comment
Спасибо! Думаю, мне это удалось. Я добавил к методу атрибут [SwaggerResponse(HttpStatusCode.OK, Download a file., typeof(FileContentResult))], а затем добавил пользовательское сопоставление в SwaggerConfig.cs: c.MapType‹FileContentResult›(() =› new Schema { тип = строка, формат = двоичный}); - person Zoltan Hernyak; 16.05.2018