我需要使用HttpWebClient一次上傳一系列文件。C#.NET HttpWebClient無法獲得文件上傳的工作;疑難解答提示?
我下面這個線索找到了示例代碼:
Upload files with HTTPWebrequest (multipart/form-data)
正如一些人報告了線,我也越來越HTTP狀態500錯誤。我已經嘗試了線程中提供的兩種解決方案,但都沒有爲我工作。似乎在請求中有間隔的問題,但我一直無法弄清楚。
問題:
我應該使用什麼樣的資源,以驗證HTTP請求的格式是否正確?
如果我複製並粘貼文件部分,應該可以手動編寫請求,對嗎?
如果您知道一些可用的示例代碼,請告訴我。
這裏是我使用的代碼:
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)。
感謝您的回答。我正在使用小提琴手。我試圖手動修改請求,但仍然失敗。 – 2010-07-15 14:01:39
謝謝,ck。我一直和提琴手一起工作,我終於想出了一個獲得正確原始要求的方法。一旦我確認了我的假設,我會在稍後的更新中解釋這篇文章。 – 2010-07-15 15:45:50
@Hugo - 很高興你能使用它 – cjk 2010-07-16 07:27:32