Как загрузить многокомпонентный файл из тела запроса в swashbuckle? - PullRequest
0 голосов
/ 21 января 2019

Как мне настроить swashbuckle в ядре .net, чтобы я мог загрузить файл из тела запроса (multipart, привязка модели значения формы отключена)?

Что я попробовал (очевидно, добавил FileUploadHelper в конфигурацию запуска swashbuckle):

public class FileUploadHelper : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        if (operation.OperationId.ToLower() == "apifileuploadpost")
        {
            operation.Parameters.Clear();
            operation.Parameters.Add(new NonBodyParameter()
            {
                Name = "File",
                In = "formData",
                Description = "uploaded file",
                Type = "file",
                Required = true,
            });
            operation.Consumes.Add("multipart/form-data");
        }
    }
}


 [HttpPost, DisableRequestSizeLimit]
 [DisableFormValueModelBinding]      
    public async Task<IActionResult> Upload()
    {
        int id = await Request.StreamFile(fileService);
        return CreatedAtAction(nameof(GetFileInfo), id);
    }

StreamFile - это метод расширения, который сохраняет содержимое файла из тела запроса в объекте filecontent (byte []), а также создает объект fileinfo с идентификатором содержимого файла и некоторой дополнительной информацией (имя, описание и т. Д.), Но возвращает только сгенерированный идентификатор. Я просто хочу иметь возможность нажать кнопку загрузки в Swagger, выбрать файл и получить возвращенный идентификатор или ответ об ошибке. Я не использую IFileForm, привязка модели значения формы отключена (в соответствии с загрузкой большого файла с использованием потоковой передачи в основной документации asp.net), и файл находится непосредственно в теле запроса, поэтому я не передаю никакой связанный с файлом параметр в методе контроллера загрузки , только 'это HttpRequest'. Это даже выполнимо в Swashbuckle?

1 Ответ

0 голосов
/ 27 июля 2019

Ваш FileUploadHelper класс выглядит хорошо. Я думаю, что проблема в том, что OperationId отличается. Это должно быть имя метода Upload. Я создал образец на основе вашего и изменил FileUploadHelper, чтобы он соответствовал маршруту, но я думаю, что это более понятно.

Вот фрагменты кода для моей версии, которая работает.

Контроллер:

[Route("api/[controller]")]
[ApiController]
public class FileUploadController : ControllerBase
{
   [HttpPost, DisableRequestSizeLimit]
   [DisableFormValueModelBinding]
   [Consumes("multipart/form-data")] // You can specify consumes here and it gets automatically added also to swagger
   public async Task<IActionResult> Upload()
   {
      int id = await Request.StreamFile(fileService);
      return CreatedAtAction(nameof(GetFileInfo), new { id = id }, null);
   }

   [HttpGet]
   [Route("{id}")]
   public async Task<IActionResult> GetFileInfo(int id)
   {
      return new JsonResult(new { id = id });
   }
}

FileUploadHelper

public class FileUploadHelper : IOperationFilter
{
   public void Apply(Operation operation, OperationFilterContext context)
   {
      if (context.ApiDescription.RelativePath == "api/FileUpload")
      {
         operation.Parameters.Clear();
         operation.Parameters.Add(new NonBodyParameter()
         {
            Name = "File",
            In = "formData",
            Description = "uploaded file",
            Type = "file",
            Required = true,
         });;
      }
   }
}

Запуск с добавленными настройками Swagger:

public class Startup
{
   public Startup(IConfiguration configuration)
   {
      Configuration = configuration;
   }

   public IConfiguration Configuration { get; }

   // This method gets called by the runtime. Use this method to add services to the container.
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

      services.AddSwaggerGen(c =>
      {
         c.SwaggerDoc("v1", new Info { Title = "File Upload API", Version = "v1" });
         c.OperationFilter<FileUploadHelper>();
      });
   }

   // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   {
      if (env.IsDevelopment())
      {
         app.UseDeveloperExceptionPage();
      }
      else
      {
         // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
         app.UseHsts();
      }

      app.UseHttpsRedirection();
      app.UseMvc();
      app.UseSwagger();
      app.UseSwaggerUI(c =>
      {
         c.SwaggerEndpoint("/swagger/v1/swagger.json", "File Upload API");
      });
   }
}

Вот так это выглядит в пользовательском интерфейсе.

Swashbuckle file upload

...