How to post form-data IFormFile with HttpClient?

23,046

Solution 1

You need to specify parameter name in MultipartFormDataContent collection matching action parameter name (csvFile) and a random file name

var multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteArrayContent, "csvFile", "filename");
var postResponse = await _client.PostAsync("offers", multipartContent);

or equivalent

var postResponse = await _client.PostAsync("offers", new MultipartFormDataContent {
    { byteArrayContent, "csvFile", "filename" }
});

Solution 2

Use this snippet:

const string url = "https://localhost:5001/api/Upload";
const string filePath = @"C:\Path\To\File.png";

using (var httpClient = new HttpClient())
{
    using (var form = new MultipartFormDataContent())
    {
        using (var fs = File.OpenRead(filePath))
        {
            using (var streamContent = new StreamContent(fs))
            {
                using (var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
                {
                    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

                    // "file" parameter name should be the same as the server side input parameter name
                    form.Add(fileContent, "file", Path.GetFileName(filePath));
                    HttpResponseMessage response = await httpClient.PostAsync(url, form);
                }
            }
        }
    }
}

Solution 3

Solved by using this code:

        const string fileName = "csvFile.csv";
        var filePath = Path.Combine("IntegrationTests", fileName);
        var bytes = File.ReadAllBytes(filePath);
        var form = new MultipartFormDataContent();
        var content = new StreamContent(new MemoryStream(bytes));
        form.Add(content, "csvFile");
        content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "csvFile",
            FileName = fileName
        };
        content.Headers.Remove("Content-Type");
        content.Headers.Add("Content-Type", "application/octet-stream; boundary=----WebKitFormBoundaryMRxYYlVt8KWT8TU3");
        form.Add(content);

        //Act
        var postResponse = await _sellerClient.PostAsync("items/upload", form);

Solution 4

This worked for me as a generic

public static Task<HttpResponseMessage> PostFormDataAsync<T>(this HttpClient httpClient, string url, string token, T data)
    {
        var content = new MultipartFormDataContent();

        foreach (var prop in data.GetType().GetProperties())
        {
            var value = prop.GetValue(data);
            if (value is FormFile)
            {
                var file = value as FormFile;
                content.Add(new StreamContent(file.OpenReadStream()), prop.Name, file.FileName);
                content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = prop.Name, FileName = file.FileName };
            }
            else
            {
                content.Add(new StringContent(JsonConvert.SerializeObject(value)), prop.Name);
            }
        }

        if (!string.IsNullOrWhiteSpace(token))
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        return httpClient.PostAsync(url, content);
    }

Solution 5

Post the attachment as an MultipartFormDataContent

var type = typeof(Startup);
            var stream = type.Assembly.GetManifestResourceStream(type, "Resources.New.docx");
        var fileContent = new StreamContent(stream);
var data = new MultipartFormDataContent
            {
                { fileContent, "file", "New.docx" }
            };

        var response = await _client.PostAsync("upload", multipartContent);

Source: https://medium.com/@woeterman_94/c-webapi-upload-files-to-a-controller-e5ccf288b0ca

Share:
23,046
Deivydas Voroneckis
Author by

Deivydas Voroneckis

Software Engineer @ Atlantis Games

Updated on May 26, 2021

Comments

  • Deivydas Voroneckis
    Deivydas Voroneckis almost 3 years

    I have backend endpoint Task<ActionResult> Post(IFormFile csvFile) and I need to call this endpoint from HttpClient. Currently I am getting Unsupported media type error. Here is my code:

    var filePath = Path.Combine("IntegrationTests", "file.csv");
    var gg = File.ReadAllBytes(filePath);
    var byteArrayContent = new ByteArrayContent(gg);
    var postResponse = await _client.PostAsync("offers", new MultipartFormDataContent
    {
        {byteArrayContent }
    });