2011-06-12 105 views
0

我想使用.net 2.0在瀏覽器窗口(或WebBrowser實例)中從C#WinForm應用程序向PHP站點發布POST,並且我需要正確獲取數據和標題 - 參數。像:使用WebBrowser-Instance從C#-WinForm上傳POST文件?

webBrowser1.Navigate("http://mypublishservice.com/publish_picture.php","_SELF",X,Y); 

問題是:什麼應該是X和Y?我知道必須在byte []數組中填充所有頭文件和文件數據,並添加一些額外的頭文件作爲字符串。我做了下面的webform的例子,並用螢火蟲對它們進行了檢查。所以我知道POST數據應該是什麼樣子。我甚至創建了一個HttpWebRequest,但是我需要一個WebBrowser(下面的原因)來啓動Post-Request。所以我迷路了。我嘗試了很多選擇,例如Upload files with HTTPWebrequest (multipart/form-data)。也許有更好的辦法,創建一個HttpWebrequest並將其傳遞給WebBrowser實例或類似的東西?

這裏是一個網頁的形式來調用publish_picture.php頁面正常工作:

<!DOCTYPE html> 
<html> 
    <head> 
    <title></title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
    </head> 
    <body> 
    <div> 
     <form enctype="multipart/form-data" action="http://mypublishservice.com/publish_picture.php" method="POST"> 

     Please choose a photo: 
     <input name="source" type="file"><br/><br/> 
     Say something about this photo: 
     <input name="message" type="text" value=""><br/><br/> 
     <input type="submit" value="Upload"/><br/> 
     </form> 
    </div> 
    </body> 
</html> 

如果你問我爲什麼要去做這樣,這裏的一些想法來捍衛我的愚蠢的決定;)

爲什麼WebBrowser實例而不是簡單的HttpWebrequest?因爲目標服務(例如Facebook)需要(或似乎需要)適當的瀏覽器! 爲什麼不是目標服務API(例如Facebook API)?發現,桌面Web通信不好(太多的400錯誤)。

更新2:

看起來更好。仍然有一個錯誤,但它可能是PHP頁面本身。這是你想到的嗎?

public static byte[] PrepareUploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values, out string header) 
    { 

     using (var requestStream = new MemoryStream()) 
     { 
      var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); //, NumberFormatInfo.InvariantInfo); 
      header = "multipart/form-data; boundary=" + boundary; 
      var boundaryBuffer2 = Encoding.ASCII.GetBytes(header); 
       requestStream.Write(boundaryBuffer2, 0, boundaryBuffer2.Length); 
       boundary = "--" + boundary; 
       // Write the values 
       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 
      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); 

       CopyStream(file.Stream, requestStream); // 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); 

      return requestStream.ToArray(); 

     } 

    } 

    public static void CopyStream(Stream input, Stream output) 
    { 
     byte[] buffer = new byte[32768]; 
     while (true) 
     { 
      int read = input.Read(buffer, 0, buffer.Length); 
      if (read <= 0) 
       return; 
      output.Write(buffer, 0, read); 
     } 
} 



public void Upload() 
{ 
    using (var stream1 = File.Open(Support.EXAMPLEIMAGE, FileMode.Open)) 
     { 
      var files = new[] 
       { 
       new UploadFile 
       { 
      Name = "source", // 1 
      Filename = Support.EXAMPLEIMAGE, 
      ContentType = "image/jpeg", // 2 
      Stream = stream1 
       } 

      }; 

      var values = new NameValueCollection 
     { 
     { "message", "a text" } // 3 

     }; 


      string contentType; // 4. do I need it 
      byte[] dataToPost = Support.PrepareUploadFiles(Support.URL, files, values, out contentType); // 5. out contentType = what should be the result vaule? 
      //PrepareUploadFiles(url, files, values, out contentType); 
      webBrowser1.Navigate(Support.URL, null, dataToPost, "Content-Type: " + contentType + Environment.NewLine); 
     } 


    } 

回答

3

個人而言,我喜歡使用ParseQueryString方法,因爲它需要適當的編碼參數:

var values = HttpUtility.ParseQueryString(string.Empty); 
values["param1"] = "param1 value"; 
values["param2"] = "param2 value"; 
values["param3"] = "param3 value"; 
var dataToPost = Encoding.UTF8.GetBytes(values.ToString()); 
var url = "http://mypublishservice.com/publish_picture.php"; 
var contentType = "Content-Type: application/x-www-form-urlencoded" + Environment.NewLine; 
webBrowser1.Navigate(url, null, dataToPost, contentType); 

現在,因爲你要上傳的文件,這將是一個有點困難。我寫了一個blog post,它說明了如何生成允許上傳多個文件的multipart/form-data請求。所以,你可以調整顯示有隻返回POST身體UploadFiles方法,而不是做實際的上傳,然後:

string contentType; 
byte[] dataToPost = PrepareUploadFiles(url, files, values, out contentType); 
webBrowser1.Navigate(url, null, dataToPost, "Content-Type: " + contentType + Environment.NewLine); 
+0

哇,這是快..我會嘗試儘快我,THX;) – MartinHappyCoding 2011-06-12 12:19:16

+1

嗨達林!我已經寫了我的結果(沒有成功;))以上..任何想法會錯誤? – MartinHappyCoding 2011-06-12 13:09:33

+0

@ user590284,您缺少內容類型標題。正確的值應該像'Content-Type:multipart/form-data;邊界=函數中使用的隨機六元數。所以你應該讓PrepareUploadFiles返回它生成的內容類型。 – 2011-06-12 13:12:45