簡體   English   中英

將文件從 ASP.NET Core web api 發布到另一個 ASP.NET Core web api

[英]Post files from ASP.NET Core web api to another ASP.NET Core web api

我們正在構建一個 Web 應用程序,它由一個 Angular2 前端、一個 ASP.NET Core Web api 公共后端和一個 ASP.NET Core Web api 專用后端組成。

將文件從 Angular2 上傳到公共后端工作。 但我們更願意將它們轉發到私有后端。

當前工作代碼

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

從那里我可以使用 file.CopyTo(fileStream); 將文件保存到磁盤。

但是,我想將那個文件或那些文件,或者理想情況下,將整個請求重新發送到我的第二個 web api 核心。

我不確定如何使用 HttpClient 類的 asp.net core 來實現這一點。

我已經嘗試了各種事情,例如

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

但是我的第二個后端得到一個空的 IFormFile。

我有一種感覺可以將文件作為流發送並在另一端重建它們,但無法使其工作。

該解決方案必須使用兩個 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();
}

數據提供者方法:

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 ;)

快樂編碼;)

接口代碼

 [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");
    }

下載源

我遇到了類似的情況 - 我需要一個代理方法來轉發文件和 JSON 數據等等。 我不想對我的代理中的數據進行任何分析,讓最終的接收者處理它。

因此,在@Anton Tykhyy 的幫助下,我得出了以下可行的解決方案:

byte[] arr = null;
using (var mems = new MemoryStream())
{
    // read entire body into memory first because it might be chunked with unknown length
    await request.Body.CopyToAsync(mems);
    await mems.FlushAsync(); // not sure if needed after CopyToAsync - better safe then sorry
    arr = mems.ToArray();
}

msg.Content = new ByteArrayContent(arr);
msg.Content.Headers.ContentLength = arr.Length;

// keep content-type header "as is" to preserve multipart boundaries etc.
msg.Content.Headers.TryAddWithoutValidation("Content-Type", request.ContentType);

var response = await _httpClient.SendAsync(msg);


我使用包含帶有 JSON 字段和多個附加文件的多部分表單數據的復雜請求對其進行了測試,並且所有數據都毫無問題地到達了我的后端服務器。

調用私有后端API時忽略HttpClient,是否可以從公共Core API項目中引用私有Core API項目,直接從Core API項目中調用控制器? 查看請求仍然為空/空。 如果請求帶有值,則問題在於 HttpClient 的使用。

理想情況下,您希望為您想要分發給消費客戶端的私有核心 API 創建一個包庫(一種 SDK)。 這就像一個包裝器/代理。 通過這種方式,您可以隔離私有后端系統,並且可以隔離地對其進行故障排除。 因此,您的公共核心 API 項目(即私有后端客戶端)可以將其引用為 nuget 包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM