web-dev-qa-db-ja.com

ASP.NET Core Web APIから別のASP.NET Core Web APIへのファイルの投稿

Angular2フロントエンド、ASP.NET Core Web APIパブリックバックエンド、ASP.NET Core Web APIプライベートバックエンドで構成されるWebアプリケーションを構築しています。

Angular2からパブリックバックエンドへのファイルのアップロードは機能します。ただし、プライベートバックエンドに転送することをお勧めします。

現在の作業コード

[HttpPost]
public StatusCodeResult Post(IFormFile file)
{
  ...
}

そこから、file.CopyTo(fileStream);を使用してファイルをディスクに保存できます。

ただし、そのファイル、またはそれらのファイル、または理想的には、リクエスト全体を2番目のWeb APIコアに再送信したいと思います。

Asp.netコアのHttpClientクラスでこれを実現する方法がわかりません。

私は次のようなあらゆることを試しました

StreamContent ss = new StreamContent(HttpContext.Request.Body);
var result = client.PostAsync("api/Values", ss).Result;

しかし、2番目のバックエンドは空のIFormFileを取得します。

ファイルをストリームとして送信し、反対側で再構築することは可能だと感じていますが、機能させることができません。

ソリューションでは、2つのWeb APIコアを使用する必要があります。

11
Dave

解決

DMZのパブリックバックエンド

[HttpPost]
public StatusCodeResult Post(IFormFile file)
{
    try
    {
        if (file != null && file.Length > 0)
        {
            using (var client = new HttpClient())
            {
                try
                {
                    client.BaseAddress = new Uri(currentPrivateBackendAddress);

                    byte[] data;
                    using (var br = new BinaryReader(file.OpenReadStream()))
                        data = br.ReadBytes((int)file.OpenReadStream().Length);

                    ByteArrayContent bytes = new ByteArrayContent(data);


                    MultipartFormDataContent multiContent = new MultipartFormDataContent();

                    multiContent.Add(bytes, "file", file.FileName);

                    var result = client.PostAsync("api/Values", multiContent).Result;


                    return StatusCode((int)result.StatusCode); //201 Created the request has been fulfilled, resulting in the creation of a new resource.

                }
                catch (Exception)
                {
                    return StatusCode(500); // 500 is generic server error
                }
            }
        }

        return StatusCode(400); // 400 is bad request

    }
    catch (Exception)
    {
        return StatusCode(500); // 500 is generic server error
    }
}

プライベートバックエンド

[HttpPost]
public void Post()
{
    //Stream bodyStream = HttpContext.Request.Body;

    if (Request.HasFormContentType)
    {
        var form = Request.Form;
        foreach (var formFile in form.Files)
        {
            var targetDirectory = Path.Combine(_appEnvironment.WebRootPath, "uploads");

            var fileName = GetFileName(formFile);

            var savePath = Path.Combine(targetDirectory, fileName);

            using (var fileStream = new FileStream(savePath, FileMode.Create))
            {
                formFile.CopyTo(fileStream);
            }                   
        }
    }          
}
16
Dave

こんにちは私は同じ問題を抱えていました、これは私のために働いたものです:

私のセットアップはnetCore MVC netCoreApiです。

私のMVCコントローラーは次のようになります:

[HttpPost("UploadFiles")]
public async Task<IActionResult> Post(List<IFormFile> files)
{
    Sp4RestClient dataPovider = new Sp4RestClient("http://localhost:60077/");

    long size = files.Sum(f => f.Length);

    foreach (var file in files)
    {
       await dataPovider.ImportFile(file);
    }

    return Ok();
}

DataProviderメソッド:

public async Task ImportFile(IFormFile file)
    {
        RestClient restClient = new RestClient(_queryBulder.BuildImportFileRequest());

        using (var content = new MultipartFormDataContent())
        {
            content.Add(new StreamContent(file.OpenReadStream())
            {
                Headers =
                {
                    ContentLength = file.Length,
                    ContentType = new MediaTypeHeaderValue(file.ContentType)
                }
            }, "File", "FileImport");

            var response = await restClient.Post<IFormFile>(content);
        }
    }

そして、少なくとも私のWebApiコントローラー:

[HttpPost]
[Route("ImportData")]
public IActionResult Import(IFormFile file)
{         
    return Ok();
}

ここで完全なコードを確認するには、RestClient Postメソッドを使用します。

public async Task<RestResult<T>> Post<T>(HttpContent content)
    {
        using (HttpClient httpClient = new HttpClient())
        {
            HttpResponseMessage response = await httpClient.PostAsync(Endpoint, content);
            if (response.StatusCode == HttpStatusCode.Created)
            {
                T result = JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
                return new RestResult<T> { Result = result, ResultCode = HttpStatusCode.OK };
            }
            RestResult<T> nonOkResult =
                new RestResult<T> { Result = default(T), ResultCode = response.StatusCode, Message = await response.Content.ReadAsStringAsync() };
            return nonOkResult;
        }
    }

//はい、HttpStatusCode.Createdが返されないことを知っています;)

ハッピーコーディング;)

5
minohimself

APIコード

 [Route("api/upload/{id}")]
    [HttpPost]
    public async Task<IActionResult> Post(string id)
    {
        var filePath = @"D:\" + id; //+ Guid.NewGuid() + ".png";
        if (Request.HasFormContentType)
        {
            var form = Request.Form;
            foreach (var formFile in form.Files)
            {
                if (formFile.Length > 0)
                {
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await formFile.CopyToAsync(stream);
                    }
                }
            }
        }
        return Ok(new { Path = filePath });
    }

バックエンド

        [Route("home/UploadFile")]
    [HttpPost]
    public IActionResult UploadFile(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return Content("file not selected");

        var client = new HttpClient();

        byte[] data;
        using (var br = new BinaryReader(file.OpenReadStream()))
            data = br.ReadBytes((int)file.OpenReadStream().Length);
        ByteArrayContent bytes = new ByteArrayContent(data);
        MultipartFormDataContent multiContent = new MultipartFormDataContent
        {
            { bytes, "file", file.FileName }
        };
        var result = client.PostAsync("http://localhost:2821/api/upload/" + file.FileName, multiContent).Result;
        return RedirectToAction("file");
    }

ソースのダウンロード

2
Godly Mathew

プライベートバックエンドAPIを呼び出すときにHttpClientを無視すると、パブリックCore APIプロジェクトからプライベートCore APIプロジェクトを参照し、Core APIプロジェクトから直接コントローラーを呼び出すことができますか?リクエストがまだnull /空であることを確認してください。要求に値が含まれている場合、問題はHttpClientの使用にあります。

理想的には、使用するクライアントに配布するプライベートCore APIのパッケージライブラリ(SDKの種類)を作成する必要があります。これはラッパー/プロキシのように機能します。この方法で、プライベートバックエンドシステムを分離し、分離してトラブルシューティングできます。したがって、パブリックコアAPIプロジェクト(プライベートバックエンドクライアント)は、nugetパッケージとしてそれを参照できます。

0
alltej