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 replacenew 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