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.