Попытка загрузить файл из контроллера с помощью метода HttpWebRequest в API Action, который имеет аргумент [FromForm]. Файл IFormFile получает значение NULL. - PullRequest
0 голосов
/ 14 сентября 2018

Я пытаюсь загрузить файл из контроллера в API в ядре asp.net mvc. Метод API, который должен получить файл, приведен ниже:

[Route("api/[controller]")]
public class ReservationController : Controller
{
    ...

    [HttpPost]
    public void UploadFile ([FromForm] IFormFile file)
    {
       ....
    }
}

Теперь в моем другом проекте есть View, который содержит элемент управления загрузкой файлов:

<form method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <div class="text-center panel-body">
        <button type="submit" class="btn btn-sm btn-primary">Add</button>
    </div>
</form>

Теперь на кнопке отправки вызывается действие контроллера:

[HttpPost]
public void AddFile(IFormFile file)
{
    HttpWebRequest apiRequest = WebRequest.Create("http://localhost:8888/api/Reservation") as HttpWebRequest;
    apiRequest.Method = "Post";
    apiRequest.ContentType = "application/octet-stream";
    string apiResponse = "";
    using (HttpWebResponse response = apiRequest.GetResponse() as HttpWebResponse)
        {
            StreamReader reader = new StreamReader(response.GetResponseStream());
            apiResponse = reader.ReadToEnd();
        }
  } 

Файл IFormFile получает файл. До этого момента он работал нормально.

Задача

Сейчас я создаю объект HttpWebRequest для загрузки моего файла с помощью метода API.

Метод API вызывается, но я возродил нулевое значение т.е. в приведенном ниже методе параметр 'file' получает значение null?

[HttpPost]
public void UploadFile ([FromForm] IFormFile file)
{
}

Почему это так? пожалуйста помогите?

Примечание

Если я просто изменю представление, чтобы включить атрибут действия в форме в URL моего API, тогда это будет работать:

<form method="post" enctype="multipart/form-data" action="http://localhost:8888/api/Reservation/UploadFile">
    <input type="file" name="file" />
    <div class="text-center panel-body">
        <button type="submit" class="btn btn-sm btn-primary">Add</button>
    </div>
</form>

Поскольку я хочу сделать это с контроллера и получить ответ, поэтому я хочу сделать вызов API из контроллера.

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

IFormFile специально работает только с кодировкой multipart/form-data, поэтому он прекрасно подходит для вашего первого действия.Однако в том запросе, который вы делаете, самая большая проблема заключается в том, что вы даже не отправляете файл в запросе.Тогда вам также нужно будет использовать multipart/form-data вместо application/octet-stream.

. Обработка с помощью WebRequest на самом деле довольно сложна, и HttpClient является предпочтительным способом делать запросы в любом случае.С HttpClient:

string apiResponse;
using (var httpClient = new HttpClient())
{
    var form = new MultipartFormDataContent();
    using (var fileStream = file.OpenReadStream())
    {
        form.Add(new StreamContent(fileStream), "file", file.Filename);
        using (var response = await httpClient.PostAsync(url, form))
        {
            response.EnsureSuccessStatusCode();
            apiResponse = await response.Content.ReadAsStringAsync();
        }
     }
 }

Я хотел сделать пример намеренно простым, но на самом деле вы не должны использовать HttpClient как этот.По большей части его следует рассматривать как синглтон, что, к счастью, довольно просто с помощью IHttpClientFactory.Во-первых, вам понадобится какой-то класс-обертка, который в любом случае является хорошей идеей, когда вы работаете с API:

public class ReservationService
{
    private readonly HttpClient _client;

    public ReservationService(HttpClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    public async Task<string> AddFileAsync(IFormFile file)
    {
        var form = new MultipartFormDataContent();
        using (var fileStream = file.OpenReadStream())
        {
            form.Add(new StreamContent(fileStream), "file", file.Filename);
            using (var response = await httpClient.PostAsync("", form))
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
        }
    }
}

Затем в ConfigureServices в Startup.cs:

services.AddScoped<ReservationService>();

services.AddHttpClient<ReservationService>(c =>
{
    c.BaseAddress = new Uri("http://localhost:8888/api/Reservation");
});

Наконец, в вашем контроллере:

public class FooController : Controller
{
    private readonly ReservationService _service;

    public FooController(ReservationService service)
    {
        _service = service ?? throw new ArgumentNullException(nameof(service));
    }

    ...

    [HttpPost]
    public async Task<IActionResult> AddFile(IFormFile file)
    {
        var apiResponse = await _service.AddFileAsync(file);
        // whatever else you want to do
    }
}
0 голосов
/ 14 сентября 2018

Вот так я обрабатываю загрузку файлов в ядре .net с помощью HttpClient

public async Task<string> UploadFile(IFormFile file)
{
    Client = new HttpClient() { BaseAddress = new Uri("http://localhost:8888/api/") };

    HttpContent fileStreamContent = new StreamContent(file.OpenReadStream());
    var multiContent = new MultipartFormDataContent
    {
        { fileStreamContent, "file", "file.FileName" }
    };

    var response = await Client.PostAsync("Reservation", multiContent);
    var data = await response.Content.ReadAsStringAsync();;
    return data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...