2010-07-15 62 views
-1

我需要使用HttpWebClient一次上傳一系列文件。C#.NET HttpWebClient無法獲得文件上傳的工作;疑難解答提示?

我下面這個線索找到了示例代碼:

Upload files with HTTPWebrequest (multipart/form-data)

正如一些人報告了線,我也越來越HTTP狀態500錯誤。我已經嘗試了線程中提供的兩種解決方案,但都沒有爲我工作。似乎在請求中有間隔的問題,但我一直無法弄清楚。

問題:

  1. 我應該使用什麼樣的資源,以驗證HTTP請求的格式是否正確?

  2. 如果我複製並粘貼文件部分,應該可以手動編寫請求,對嗎?

  3. 如果您知道一些可用的示例代碼,請告訴我。

這裏是我使用的代碼:

public static void UploadFilesToRemoteUrl(string url, string[] files, 
string logpath, NameValueCollection nvc) 
{ 

long length = 0; 
string boundary = "----------------------------" + 
DateTime.Now.Ticks.ToString("x"); 


HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url); 
httpWebRequest2.ContentType = "multipart/form-data; boundary=" + 
boundary; 
httpWebRequest2.Method = "POST"; 
httpWebRequest2.KeepAlive = true; 
httpWebRequest2.Credentials = 
System.Net.CredentialCache.DefaultCredentials; 



Stream memStream = new System.IO.MemoryStream(); 

byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + 
boundary + "\r\n"); 


string formdataTemplate = "\r\n--" + boundary + 
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; 

foreach (string key in nvc.Keys) 
{ 
    string formitem = string.Format(formdataTemplate, key, nvc[key]); 
    byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); 
    memStream.Write(formitembytes, 0, formitembytes.Length); 
} 


memStream.Write(boundarybytes, 0, boundarybytes.Length); 

string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n"; 

for (int i = 0; i < files.Length; i++) 
{ 

    //string header = string.Format(headerTemplate, "file" + i, files[i]); 
    string header = string.Format(headerTemplate, "uplTheFile", files[i]); 

    byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); 

    memStream.Write(headerbytes, 0, headerbytes.Length); 


    FileStream fileStream = new FileStream(files[i], FileMode.Open, 
    FileAccess.Read); 
    byte[] buffer = new byte[1024]; 

    int bytesRead = 0; 

    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 
    { 
     memStream.Write(buffer, 0, bytesRead); 

    } 


    memStream.Write(boundarybytes, 0, boundarybytes.Length); 


    fileStream.Close(); 
} 

httpWebRequest2.ContentLength = memStream.Length; 

Stream requestStream = httpWebRequest2.GetRequestStream(); 

memStream.Position = 0; 
byte[] tempBuffer = new byte[memStream.Length]; 
memStream.Read(tempBuffer, 0, tempBuffer.Length); 
memStream.Close(); 
requestStream.Write(tempBuffer, 0, tempBuffer.Length); 
requestStream.Close(); 


WebResponse webResponse2 = httpWebRequest2.GetResponse(); 

Stream stream2 = webResponse2.GetResponseStream(); 
StreamReader reader2 = new StreamReader(stream2); 


MessageBox.Show(reader2.ReadToEnd()); 

webResponse2.Close(); 
httpWebRequest2 = null; 
webResponse2 = null; 
} 

更新:

感謝CK鼓勵我使用招繼續。這是我需要找到解決這個問題的方法。

現在讓我回答這裏的問題。

1.我應該使用什麼資源來驗證HTTP請求的格式是否正確? a)該標準。有RFC1867 http://www.faqs.org/rfcs/rfc1867.html。很好的閱讀。它解釋了多次上傳應該發生的人,以及您如何處理其他表單數據。其侷限性在於,它並不直接說明如何根據每個頭和值之間的CRLF數來格式化請求。我懷疑這些信息可能在HTTP RFC 2616 http://www.w3.org/Protocols/rfc2616/rfc2616.html中,但那段時間的閱讀時間稍長一些。另外,在它的不同實現之間可能還有一些解釋空間。

b)實際例子。獲得真實例子的獲勝組合是一起使用捲曲和提琴手。我能夠通過curl發送正確的上傳請求,但curl的--trace-ascii沒有給我我需要的原始標題。我基於它製作的近似值一直沒有完成,而提琴手似乎沒有捕獲它的流量。

然後我找到一個解釋curl不使用系統代理的鏈接。所以爲了捕捉它在提琴手上的流量,必須輸入curl -x 127.0.0.1:8888 www.happysmurfs.com現在我得到了我需要的原始頭文件。現在,使用正確的原始頭文件,對代碼進行故障排除非常簡單,因爲我有另一個文本頭與其進行比較。

2.如果我複製並粘貼文件部分,應該可以手動編寫請求,對嗎? 是的,它似乎是可能的,但正如ck提到的那樣,從小提琴手那裏得到一個可行的,經過驗證的標題然後從那裏進行修改要容易得多。

3.如果您知道一些可用的示例代碼,請告訴我。 上面的代碼應該工作,但要注意這一行:

string formdataTemplate = "\r\n--" + boundary + 
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; 

第一\ r \ n不應該存在。另外,在標題或邊界的末尾不應該沒有雙重新行,(\ r \ n)。

回答

1

您應該使用Fiddler來驗證您的程序發送的內容與手動進行的操作相同。

+0

感謝您的回答。我正在使用小提琴手。我試圖手動修改請求,但仍然失敗。 – 2010-07-15 14:01:39

+0

謝謝,ck。我一直和提琴手一起工作,我終於想出了一個獲得正確原始要求的方法。一旦我確認了我的假設,我會在稍後的更新中解釋這篇文章。 – 2010-07-15 15:45:50

+0

@Hugo - 很高興你能使用它 – cjk 2010-07-16 07:27:32