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コアを使用する必要があります。
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);
}
}
}
}
こんにちは私は同じ問題を抱えていました、これは私のために働いたものです:
私のセットアップは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が返されないことを知っています;)
ハッピーコーディング;)
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");
}
プライベートバックエンドAPIを呼び出すときにHttpClientを無視すると、パブリックCore APIプロジェクトからプライベートCore APIプロジェクトを参照し、Core APIプロジェクトから直接コントローラーを呼び出すことができますか?リクエストがまだnull /空であることを確認してください。要求に値が含まれている場合、問題はHttpClientの使用にあります。
理想的には、使用するクライアントに配布するプライベートCore APIのパッケージライブラリ(SDKの種類)を作成する必要があります。これはラッパー/プロキシのように機能します。この方法で、プライベートバックエンドシステムを分離し、分離してトラブルシューティングできます。したがって、パブリックコアAPIプロジェクト(プライベートバックエンドクライアント)は、nugetパッケージとしてそれを参照できます。