Here’s a re-usable code-snippet for POSTing multipart/mime requests.
Sample Usage:
Status = "Logging In"; PostRequest( this.LoginUri, null, /* not posting any files */ new { username = UserName, password = Password }, (WebResponse response) => { string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); Status = "Logged In"; }); PostRequest( this.LoginUri, new [] { new UploadFile { ContentType="text/plain", Name="files", Filename="myfile.txt", Stream=File.OpenRead("myfile.txt")}}, new { username = UserName, password = Password }, (WebResponse response) => { string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); Status = "File Uploaded"; });
private CookieContainer _cookieContainer = new CookieContainer(); private void PostRequest(Uri address, IEnumerable<UploadFile> files, object values, Action<WebResponse> handleResponse) { PostRequest(address, files, ToNameValueCollection(values), handleResponse); } private void PostRequest(Uri address, IEnumerable<UploadFile> files, NameValueCollection values, Action<WebResponse> handleResponse) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address); request.CookieContainer = _cookieContainer; request.Method = "POST"; var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo); request.ContentType = "multipart/form-data; boundary=" + boundary; boundary = "--" + boundary; request.BeginGetRequestStream(new AsyncCallback(r => { using (var requestStream = request.EndGetRequestStream(r)) { // Write the values if (values != null) { foreach (string name in values.Keys) { var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); } } // Write the files if (files != null) { foreach (var file in files) { var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); file.Stream.CopyTo(requestStream); buffer = Encoding.ASCII.GetBytes(Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); } } var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--"); requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length); requestStream.Close(); request.BeginGetResponse(new AsyncCallback(r2 => { try { var response = request.EndGetResponse(r2); handleResponse(response); } catch (WebException exc) { Status = exc.Message; } }), null); } }), null); } // PostRequest private static NameValueCollection ToNameValueCollection(object o) { var nvc = new NameValueCollection(); o.GetType().GetProperties() .ToList() .ForEach(pi => nvc.Add(pi.Name, pi.GetValue(o, null).ToString())); return nvc; } // Helper class public class UploadFile { public UploadFile() { ContentType = "application/octet-stream"; } public string Name { get; set; } public string Filename { get; set; } public string ContentType { get; set; } public Stream Stream { get; set; } }
The post Asynchronous Multipart POST with C# appeared first on Chui's Counterpoint.