Metro XAML Rating [[R]]ating Control www.perpetuumsoft.com
Star Tech Corner Star Tech Corner
TUESDAY, MARCH MA[[R]]CH 03, 2009
[[Silverlight ]] Multi-part File Upload Form Post
[[Silverlight ]] not actually very web friendly. It lacks of built-in support for the current HTML form post protocol. So, we have to write it our own. I have written an extension class and two serializer classes, one for normal form post (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 HttpWeb[[R]]equest request, object parameters, AsyncCallback callback) { request.Method = "POST"; request.ContentType = "applicatio n/x-www-form-urlencoded"; request.BeginGetRequestStreamBeginGet[[R]]equestStream(new AsyncCallback(asyncResult async[[R]]esult => { Stream stream = request.EndGe tRequestStreamt[[R]]equestStream(asyncResultasync[[R]]esult); DataContractQueryStringSerial izer ser = new DataContractQueryStringSeria lizer(); ser.WriteObject(stream, param eters); stream.Close(); request.BeginGetResponseBeginGet[[R]]esponse(call back, request); }), request); }
public static void PostMultiPartAsync (this HttpWebRequest HttpWeb[[R]]equest request, object parame ters, AsyncCallback callback) { request.Method = "POST"; string boundary = "---------------" + DateTime.Now.Ticks.ToString(); request.ContentType = "multipart/form-data; boundary=" + boundary; request.BeginGetRequestStreamBeginGet[[R]]equestStream(new AsyncCallback(asyncResult async[[R]]esult => { Stream stream = request.EndGe tRequestStreamt[[R]]equestStream(asyncResultasync[[R]]esult);
DataContractMultiPartSerializ er ser = new DataContractMultiPartSerialize r(boundary); ser.WriteObject(stream, param eters); stream.Close(); request.BeginGetResponseBeginGet[[R]]esponse(call back, request); }), request); }
public class DataContractQueryStringSeria lizer
ribute member = attribute as DataMemberAttr ibute;
<blockquote>0}={1}&", member.Name ?? prop.Name, prop. GetValue(data)); } } } foreach (var prop in data .GetType().GetProperties()) { if (prop.CanReadCan[[R]]ead) { foreach (var attr ibute in prop.GetCustomAttributes(true)) {</blockquote>
is DataMemberAttribute)
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 Fil eInfo; writer.WriteLine(@"Conten t-Disposition: form-data; name=""{0}""; fil ename=""{1}""", key, f.Name); writer.WriteLine("Content -Type: application/octet-stream"); writer.WriteLine("Content -Length: " + f.Length); writer.WriteLine(); writer.Flush(); Stream output = writer.Ba seStream; Stream input = f.OpenReadOpen[[R]]ead
byte[] buffer = new byte[ 4096]; for (int size = input.Rea d(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(@"Conten t-Disposition: form-data; name=""{0}""", ke
ribute member = attribute as DataMemberAttr ibute;
iter, member.Name ?? prop.Name, prop.GetVal ue(data)); } } } foreach (var prop in data .GetType().GetProperties()) { if (prop.CanReadCan[[R]]ead) { foreach (var attr ibute in prop.GetCustomAttributes(true)) {
is DataMemberAttribute)
} } } } } 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);
public partial class Page : UserControl
public Page() { InitializeComponent(); // Create a request object HttpWebRequest HttpWeb[[R]]equest request = (HttpWeb Request[[R]]equest)WebRequestWeb[[R]]equest.Create(new Uri("http://l ocalhost/rms/test.php")); OpenFileDialog dlg = new OpenFile Dialog(); if (dlg.ShowDialog().Value) { request.PostMultiPartAsync(ne w Dictionary<string, object> { { "x", "1" } , { "y", dlg.File } }, new AsyncCallback(as yncResult ync[[R]]esult => { HttpWebResponse HttpWeb[[R]]esponse response = (HttpWebResponseHttpWeb[[R]]esponse)request.EndGetResponseEndGet[[R]]esponse(a syncResultsync[[R]]esult);
Stream responseStream = r esponse.GetResponseStreamGet[[R]]esponseStream(); StreamReader Stream[[R]]eader reader = new StreamReaderStream[[R]]eader(responseStream); this.Dispatcher.BeginInvo ke(delegate { // output is a TextBl
output.Text = reader. ReadToEnd[[R]]eadToEnd(); response.Close(); }); })); } }
Since it is able to serialize data contract, you could actually replace
Cool! The multipart handling was exactly what I needed. Nice work!
Reply[[R]]eply
Anonymous 4:53 PM
Hi, I failed in EndGetResponseEndGet[[R]]esponse(), and got security exception. What will the encoding data would like? Could you give me an example?
Thanks a lot~
Reply[[R]]eply
Naveen 7:10 PM
Could you post the receiving recei[[vi]]ng part? Meaning, how to take the multipart request in the server (Jersey) and process the multipart request?
Reply[[R]]eply
Shane Ng 1:13 AM
It's just a multi-part form
standard Java Web Container (e.g. [[Tomcat]]) will be able to process it natively.
Reply[[R]]eply
Comment as: Select profile...
PreviewPre[[vi]]ew