Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Post files from ASP.NET Core web api to another ASP.NET Core web api

We are building a web application that consist of an Angular2 frontend, a ASP.NET Core web api public backend, and a ASP.NET Core web api private backend.

Uploading files from Angular2 to the public backend works. But we would prefer to post them forward to the private backend.

Current working code

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

From there I can save the file to disk using file.CopyTo(fileStream);

However, I want to re-send that file, or those files, or, ideally, the whole request to my second web api core.

I am not sure how to achieve this with the HttpClient class of asp.net core.

I've tried all kinds of things such as

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

But my second backend gets an empty IFormFile.

I have a feeling it is possible to send the file(s) as a stream and reconstruct them on the other side, but can't get it to work.

The solution must use two web api core.

like image 503
Dave Avatar asked Sep 08 '16 17:09

Dave


3 Answers

Solution

Public backend in 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
    }
}

Private backend

[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);
            }                   
        }
    }          
}
like image 194
Dave Avatar answered Oct 17 '22 23:10

Dave


Hi i had the same issue and this is what worked for me :

My setup is netCore MVC netCoreApi.

My MVC Controller looks like :

[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 Method :

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

And least my WebApi Controller :

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

To see the complete code here is my RestClient Post method :

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

// Yeah i know im not getting HttpStatusCode.Created back ;)

happy coding ;)

like image 28
minohimself Avatar answered Oct 17 '22 23:10

minohimself


API Code

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

Back End

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

Download Source

like image 2
Godly Mathew Avatar answered Oct 18 '22 00:10

Godly Mathew