C# HttpClient 4.5 multipart/form-data upload

C#Upload.Net 4.5Multipartform DataDotnet Httpclient

C# Problem Overview


Does anyone know how to use the HttpClient in .Net 4.5 with multipart/form-data upload?

I couldn't find any examples on the internet.

C# Solutions


Solution 1 - C#

my result looks like this:

public static async Task<string> Upload(byte[] image)
{
     using (var client = new HttpClient())
     {
         using (var content =
             new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
         {
             content.Add(new StreamContent(new MemoryStream(image)), "bilddatei", "upload.jpg");

              using (
                 var message =
                     await client.PostAsync("http://www.directupload.net/index.php?mode=upload", content))
              {
                  var input = await message.Content.ReadAsStringAsync();

                  return !string.IsNullOrWhiteSpace(input) ? Regex.Match(input, @"http://\w*\.directupload\.net/images/\d*/\w*\.[a-z]{3}").Value : null;
              }
          }
     }
}

Solution 2 - C#

It works more or less like this (example using an image/jpg file):

async public Task<HttpResponseMessage> UploadImage(string url, byte[] ImageData)
{
    var requestContent = new MultipartFormDataContent(); 
    //    here you can specify boundary if you need---^
    var imageContent = new ByteArrayContent(ImageData);
    imageContent.Headers.ContentType = 
        MediaTypeHeaderValue.Parse("image/jpeg");

    requestContent.Add(imageContent, "image", "image.jpg");

    return await client.PostAsync(url, requestContent);
}

(You can requestContent.Add() whatever you want, take a look at the HttpContent descendant to see available types to pass in)

When completed, you'll find the response content inside HttpResponseMessage.Content that you can consume with HttpContent.ReadAs*Async.

Solution 3 - C#

This is an example of how to post string and file stream with HTTPClient using MultipartFormDataContent. The Content-Disposition and Content-Type need to be specified for each HTTPContent:

Here's my example. Hope it helps:

private static void Upload()
{
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");
           
        using (var content = new MultipartFormDataContent())
        {
            var path = @"C:\B2BAssetRoot\files\596086\596086.1.mp4";

            string assetName = Path.GetFileName(path);

            var request = new HTTPBrightCoveRequest()
                {
                    Method = "create_video",
                    Parameters = new Params()
                        {
                            CreateMultipleRenditions = "true",
                            EncodeTo = EncodeTo.Mp4.ToString().ToUpper(),
                            Token = "x8sLalfXacgn-4CzhTBm7uaCxVAPjvKqTf1oXpwLVYYoCkejZUsYtg..",
                            Video = new Video()
                                {
                                    Name = assetName,
                                    ReferenceId = Guid.NewGuid().ToString(),
                                    ShortDescription = assetName
                                }
                        }
                };

            //Content-Disposition: form-data; name="json"
            var stringContent = new StringContent(JsonConvert.SerializeObject(request));
            stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
            content.Add(stringContent, "json");

            FileStream fs = File.OpenRead(path);

            var streamContent = new StreamContent(fs);
            streamContent.Headers.Add("Content-Type", "application/octet-stream");
            //Content-Disposition: form-data; name="file"; filename="C:\B2BAssetRoot\files\596090\596090.1.mp4";
            streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
            content.Add(streamContent, "file", Path.GetFileName(path));
               
            //content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

            Task<HttpResponseMessage> message = client.PostAsync("http://api.brightcove.com/services/post", content);

            var input = message.Result.Content.ReadAsStringAsync();
            Console.WriteLine(input.Result);
            Console.Read();
        }
    }
}

Solution 4 - C#

Here is another example on how to use HttpClient to upload a multipart/form-data.

It uploads a file to a REST API and includes the file itself (e.g. a JPG) and additional API parameters. The file is directly uploaded from local disk via FileStream.

See here for the full example including additional API specific logic.

public static async Task UploadFileAsync(string token, string path, string channels)
{
	// we need to send a request with multipart/form-data
	var multiForm = new MultipartFormDataContent();
				
	// add API method parameters
	multiForm.Add(new StringContent(token), "token");
	multiForm.Add(new StringContent(channels), "channels");

	// add file and directly upload it
	FileStream fs = File.OpenRead(path);
	multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(path));

	// send request to API
	var url = "https://slack.com/api/files.upload";
	var response = await client.PostAsync(url, multiForm);
}

Solution 5 - C#

Try this its working for me.

private static async Task<object> Upload(string actionUrl)
{
	Image newImage = Image.FromFile(@"Absolute Path of image");
	ImageConverter _imageConverter = new ImageConverter();
	byte[] paramFileStream= (byte[])_imageConverter.ConvertTo(newImage, typeof(byte[]));

	var formContent = new MultipartFormDataContent
	{
		// Send form text values here
		{new StringContent("value1"),"key1"},
		{new StringContent("value2"),"key2" },
		// Send Image Here
		{new StreamContent(new MemoryStream(paramFileStream)),"imagekey","filename.jpg"}
	};

	var myHttpClient = new HttpClient();
	var response = await myHttpClient.PostAsync(actionUrl.ToString(), formContent);
	string stringContent = await response.Content.ReadAsStringAsync();

	return response;
}

Solution 6 - C#

Here's a complete sample that worked for me. The boundary value in the request is added automatically by .NET.

var url = "http://localhost/api/v1/yourendpointhere";
var filePath = @"C:\path\to\image.jpg";

HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();

FileStream fs = File.OpenRead(filePath);
var streamContent = new StreamContent(fs);

var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

form.Add(imageContent, "image", Path.GetFileName(filePath));
var response = httpClient.PostAsync(url, form).Result;

Solution 7 - C#

I'm adding a code snippet which shows on how to post a file to an API which has been exposed over DELETE http verb. This is not a common case to upload a file with DELETE http verb but it is allowed. I've assumed Windows NTLM authentication for authorizing the call.

The problem that one might face is that all the overloads of HttpClient.DeleteAsync method have no parameters for HttpContent the way we get it in PostAsync method

var requestUri = new Uri("http://UrlOfTheApi");
using (var streamToPost = new MemoryStream("C:\temp.txt"))
using (var fileStreamContent = new StreamContent(streamToPost))
using (var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true })
using (var httpClient = new HttpClient(httpClientHandler, true))
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUri))
using (var formDataContent = new MultipartFormDataContent())
{
	formDataContent.Add(fileStreamContent, "myFile", "temp.txt");
	requestMessage.Content = formDataContent;
	var response = httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
	
	if (response.IsSuccessStatusCode)
	{
		// File upload was successfull
	}
	else
	{
		var erroResult = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
		throw new Exception("Error on the server : " + erroResult);
	}
}

You need below namespaces at the top of your C# file:

using System;
using System.Net;
using System.IO;
using System.Net.Http;

P.S. You are seeing a number of using blocks(IDisposable pattern) in the above code snippet which doesn't look very clean. Unfortunately, the syntax of using construct doesn't support initializing multiple variables in single statement.

Solution 8 - C#

Example with preloader Dotnet 3.0 Core

ProgressMessageHandler processMessageHander = new ProgressMessageHandler();

processMessageHander.HttpSendProgress += (s, e) =>
{
	if (e.ProgressPercentage > 0)
	{
		ProgressPercentage = e.ProgressPercentage;
		TotalBytes = e.TotalBytes;
		progressAction?.Invoke(progressFile);
	}
};

using (var client = HttpClientFactory.Create(processMessageHander))
{
	var uri = new Uri(transfer.BackEndUrl);
	client.DefaultRequestHeaders.Authorization =
	new AuthenticationHeaderValue("Bearer", AccessToken);

	using (MultipartFormDataContent multiForm = new MultipartFormDataContent())
	{
		multiForm.Add(new StringContent(FileId), "FileId");
		multiForm.Add(new StringContent(FileName), "FileName");
		string hash = "";

		using (MD5 md5Hash = MD5.Create())
		{
			var sb = new StringBuilder();
			foreach (var data in md5Hash.ComputeHash(File.ReadAllBytes(FullName)))
			{
				sb.Append(data.ToString("x2"));
			}
			hash = result.ToString();
		}
		multiForm.Add(new StringContent(hash), "Hash");

		using (FileStream fs = File.OpenRead(FullName))
		{
			multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(FullName));
			var response = await client.PostAsync(uri, multiForm);
			progressFile.Message = response.ToString();
			
			if (response.IsSuccessStatusCode) {
				progressAction?.Invoke(progressFile);
			} else {
				progressErrorAction?.Invoke(progressFile);
			}
			response.EnsureSuccessStatusCode();
		}
	}
}

Solution 9 - C#

X509Certificate clientKey1 = null;
clientKey1 = new X509Certificate(AppSetting["certificatePath"],
AppSetting["pswd"]);
string url = "https://EndPointAddress";
FileStream fs = File.OpenRead(FilePath);
var streamContent = new StreamContent(fs);

var FileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
FileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("ContentType");
var handler = new WebRequestHandler();


handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(clientKey1);
handler.ServerCertificateValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) =>
{
	return true;
};


using (var client = new HttpClient(handler))
{
	// Post it
	HttpResponseMessage httpResponseMessage = client.PostAsync(url, FileContent).Result;

	if (!httpResponseMessage.IsSuccessStatusCode)
	{
		string ss = httpResponseMessage.StatusCode.ToString();
	}
}

Solution 10 - C#

public async Task<object> PassImageWithText(IFormFile files)
{
	byte[] data;
	string result = "";
	ByteArrayContent bytes;

	MultipartFormDataContent multiForm = new MultipartFormDataContent();
	
	try
	{
		using (var client = new HttpClient())
		{
			using (var br = new BinaryReader(files.OpenReadStream()))
			{
				data = br.ReadBytes((int)files.OpenReadStream().Length);
			}

			bytes = new ByteArrayContent(data);
			multiForm.Add(bytes, "files", files.FileName);
			multiForm.Add(new StringContent("value1"), "key1");
			multiForm.Add(new StringContent("value2"), "key2");

			var res = await client.PostAsync(_MEDIA_ADD_IMG_URL, multiForm);
		}
	}
	catch (Exception e)
	{
		throw new Exception(e.ToString());
	}
	
	return result;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionidentView Question on Stackoverflow
Solution 1 - C#identView Answer on Stackoverflow
Solution 2 - C#WDRustView Answer on Stackoverflow
Solution 3 - C#Johnny ChuView Answer on Stackoverflow
Solution 4 - C#Erik KalkokenView Answer on Stackoverflow
Solution 5 - C#Vishnu KumarView Answer on Stackoverflow
Solution 6 - C#nthpixelView Answer on Stackoverflow
Solution 7 - C#RBTView Answer on Stackoverflow
Solution 8 - C#D.OlegView Answer on Stackoverflow
Solution 9 - C#Rajenthiran TView Answer on Stackoverflow
Solution 10 - C#Jack The RipperView Answer on Stackoverflow