DataContractQueryStringSerializer
) while the other for multipart upload form post (DataContractMultiPartSerializer
).If you only want to have the working code, just copy the code below. Detail explanation is available at Multi-Part Form Post in Shane's Shelf
public static class Extensions { public static void PostFormAsync(this HttpWebRequest request, object parameters, AsyncCallback callback) { request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.BeginGetRequestStream(new AsyncCallback(asyncResult => { Stream stream = request.EndGetRequestStream(asyncResult); DataContractQueryStringSerializer ser = new DataContractQueryStringSerializer(); ser.WriteObject(stream, parameters); stream.Close(); request.BeginGetResponse(callback, request); }), request); } public static void PostMultiPartAsync(this HttpWebRequest request, object parameters, AsyncCallback callback) { request.Method = "POST"; string boundary = "---------------" + DateTime.Now.Ticks.ToString(); request.ContentType = "multipart/form-data; boundary=" + boundary; request.BeginGetRequestStream(new AsyncCallback(asyncResult => { Stream stream = request.EndGetRequestStream(asyncResult); DataContractMultiPartSerializer ser = new DataContractMultiPartSerializer(boundary); ser.WriteObject(stream, parameters); stream.Close(); request.BeginGetResponse(callback, request); }), request); } } public class DataContractQueryStringSerializer { public void WriteObject(Stream stream, object data) { StreamWriter writer = new StreamWriter(stream); if (data != null) { if (data is Dictionary<string, string>) { foreach (var entry in data as Dictionary<string, string>) { writer.Write("{0}={1}&", entry.Key, entry.Value); } } else { foreach (var prop in data.GetType().GetFields()) { foreach (var attribute in prop.GetCustomAttributes(true)) { if (attribute is DataMemberAttribute) { DataMemberAttribute member = attribute as DataMemberAttribute; writer.Write("{0}={1}&", member.Name ?? prop.Name, prop.GetValue(data)); } } } foreach (var prop in data.GetType().GetProperties()) { if (prop.CanRead) { foreach (var attribute in prop.GetCustomAttributes(true)) { if (attribute is DataMemberAttribute) { DataMemberAttribute member = attribute as DataMemberAttribute; writer.Write("{0}={1}&", member.Name ?? prop.Name, prop.GetValue(data, null)); } } } } } writer.Flush(); } } } public class DataContractMultiPartSerializer { private string boundary; public DataContractMultiPartSerializer(string boundary) { this.boundary = boundary; } private void WriteEntry(StreamWriter writer, string key, object value) { if (value != null) { writer.Write("--"); writer.WriteLine(boundary); if (value is FileInfo) { FileInfo f = value as FileInfo; writer.WriteLine(@"Content-Disposition: form-data; name=""{0}""; filename=""{1}""", key, f.Name); writer.WriteLine("Content-Type: application/octet-stream"); writer.WriteLine("Content-Length: " + f.Length); writer.WriteLine(); writer.Flush(); Stream output = writer.BaseStream; Stream input = f.OpenRead(); byte[] buffer = new byte[4096]; for (int size = input.Read(buffer, 0, buffer.Length); size > 0; size = input.Read(buffer, 0, buffer.Length)) { output.Write(buffer, 0, size); } output.Flush(); writer.WriteLine(); } else { writer.WriteLine(@"Content-Disposition: form-data; name=""{0}""", key); writer.WriteLine(); writer.WriteLine(value.ToString()); } } } public void WriteObject(Stream stream, object data) { StreamWriter writer = new StreamWriter(stream); if (data != null) { if (data is Dictionary<string, object>) { foreach (var entry in data as Dictionary<string, object>) { WriteEntry(writer, entry.Key, entry.Value); } } else { foreach (var prop in data.GetType().GetFields()) { foreach (var attribute in prop.GetCustomAttributes(true)) { if (attribute is DataMemberAttribute) { DataMemberAttribute member = attribute as DataMemberAttribute; WriteEntry(writer, member.Name ?? prop.Name, prop.GetValue(data)); } } } foreach (var prop in data.GetType().GetProperties()) { if (prop.CanRead) { foreach (var attribute in prop.GetCustomAttributes(true)) { if (attribute is DataMemberAttribute) { DataMemberAttribute member = attribute as DataMemberAttribute; WriteEntry(writer, member.Name ?? prop.Name, prop.GetValue(data, null)); } } } } } } writer.Write("--"); writer.Write(boundary); writer.WriteLine("--"); writer.Flush(); } }The usage is as follows:
First a PHP file
<?php print_r($_REQUEST); $src = $_FILES['y']['tmp_name']; $dest = "C:\\Windows\\Temp\\".$_FILES['y']['name']; echo $src; echo "\r\n"; echo $dest; echo @copy($src, $dest); ?>Then the Page control
public partial class Page : UserControl { public Page() { InitializeComponent(); // Create a request object HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("http://localhost/rms/test.php")); OpenFileDialog dlg = new OpenFileDialog(); if (dlg.ShowDialog().Value) { request.PostMultiPartAsync(new Dictionary<string, object> { { "x", "1" }, { "y", dlg.File } }, new AsyncCallback(asyncResult => { HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); this.Dispatcher.BeginInvoke(delegate { // output is a TextBlock output.Text = reader.ReadToEnd(); response.Close(); }); })); } } }Since it is able to serialize data contract, you could actually replace
new Dictionary<string, object> { { "x", "1" }, { "y", dlg.File } }
with
new Point(){X=1, Y=2}
given the point class is like this:
[DataContract] public class Point { [DataMember] public int X { get; set; } [DataMember(Name="y")] public int Y { get; set; } }
4 comments:
Cool! The multipart handling was exactly what I needed. Nice work!
Hi,
I failed in EndGetResponse(), and got security exception.
What will the encoding data would like?
Could you give me an example?
Thanks a lot~
Could you post the receiving part? Meaning, how to take the multipart request in the server (Jersey) and process the multipart request?
It's just a multi-part form post. PHP and standard Java Web Container (e.g. Tomcat) will be able to process it natively.
Post a Comment