2009-12-09 65 views
12

我正嘗試使用.NET/C#將文件和一些參數發送到我的站點。閱讀了一些可以做幾個參數或者一個文件的教程後,我試圖將它們結合起來失敗。這裏是我嘗試這樣做:帶有文件和參數的WebRequest POST

WebRequest req = WebRequest.Create(baseURL + "upload"); 
req.Credentials = new NetworkCredential(username, password); 
String boundary = "B0unD-Ary"; 
req.ContentType = "multipart/form-data; boundary=" + boundary; 
req.Method = "POST"; 
((HttpWebRequest)req).UserAgent = "UploadTester v0.1"; 

string postData = "--" + boundary + "\nContent-Disposition: form-data\n"; 
postData += "myId=123&someFk=456"; 
postData += "\n--" + boundary + "\nContent-Disposition: form-data; name=\"file\" filename=\"upload.pdf\" Content-Type: application/pdf\n\n"; 
byte[] byteArray = Encoding.UTF8.GetBytes(postData); 

byte[] filedata = null; 
using (BinaryReader reader = new BinaryReader(File.OpenRead("myfile.pdf"))) 
    filedata = reader.ReadBytes((int)reader.BaseStream.Length); 

req.ContentLength = byteArray.Length + filedata.Length; 
req.GetRequestStream().Write(byteArray, 0, byteArray.Length); 
req.GetRequestStream().Write(filedata, 0, filedata.Length); 

WebResponse response = req.GetResponse(); 
Stream data = response.GetResponseStream(); 
StreamReader sReader = new StreamReader(data); 
String sResponse = sReader.ReadToEnd(); 
response.Close(); 

當我執行它,我得到一個500例外,說:「頭一節有超過10240個bnytes(也許它不能正常終止)」和Wireshark通知我,發送的請求是格式不正確的包,MIME multipart格式不正確。

可能有幾個問題在這裏,所以請讓我知道所有你能發現的問題

更新:以MIME從C#/。NET分開,我已經催生了一個線程在這裏:https://stackoverflow.com/questions/1880002/error-in-mime-packet-for-http-post

更新2:因此,後端的內容長度確實存在問題,即可用於讀取的字節數量小於所述的內容長度。但!如果我相應地減少了req.ContentLength中的內容長度,那麼我沒有足夠大的緩衝區大小來發送數據。有什麼建議麼?

更新3:事實上,它看起來像頭有一個過大的尺寸相比,它包含的數據量

+0

如果您使用的是.NET> = 4.0,請跳至我的答案以獲取更簡單的方法。 – Joshcodes 2013-06-04 18:45:22

回答

11

的問題是,你缺少一個「\ n」。下面一行:

string postData = "--" + boundary + "\nContent-Disposition: form-data\n"; 

應該是:

string postData = "--" + boundary + "\nContent-Disposition: form-data\n\n"; 

這行:

postData += "\n--" + boundary + "\nContent-Disposition: form-data; name=\"file\" filename=\"upload.pdf\" Content-Type: application/pdf\n\n" 

丟失之前 '內容類型' 一 '\ n'。它應該是:

postData += "\n--" + boundary + "\nContent-Disposition: form-data; name=\"file\" filename=\"upload.pdf\"\nContent-Type: application/pdf\n\n" 
+3

感謝您指出這些。經過15個小時的調試後,我發現主要問題:.NET引擎將我的所有換行符轉換爲CR + Newline,因此寫入的字節數比我在內容長度中指定的要多。因此,對於將來有類似問題的任何人:將所有換行符替換爲CR +換行符(\ n到\ r \ n) – niklassaers 2009-12-10 12:04:31

+0

當我使用這種方法獲取多部分:期望的最終邊界?任何想法如何解決這個問題? – 2012-05-24 09:04:07

1

我想眼前的問題是申報與實際長度之間的不匹配。

你在哪裏錯算了我不確定,但如果我沒有記錯,長度應該包括除第一行外的每個字節的響應(包括標題)。

可以肯定我將建立一個簡單的HTML頁面,生成你想要的職位,並檢查了後用小提琴手(或螢火蟲)

+0

啊,謝謝,這是一個很好的提示。可惜我必須親自去做這件事。我敢肯定,成千上萬的人寫了類似這樣的代碼,使用標準庫會更容易。 – niklassaers 2009-12-09 16:16:43

+0

嗯,但我的內容長度正確設置爲129597字節,而不是10240附近的任何地方。:-I – niklassaers 2009-12-09 17:00:17

+0

而不是寫入請求流,我會將它寫入文件流,並查看有多少字節,並確保內容長度匹配。 或者,寫入一個MemoryStream,然後你可以做一個memoryStream.ToArra()並從中獲取內容長度。 – feroze 2009-12-09 17:26:37

0

試圖改變

string postData = "--" + boundary + "\nContent-Disposition: form-data\n"; 

string postData = "\n\n--" + boundary + "\nContent-Disposition: form-data\n\n"; 

,更好的同時更換所有\ n至用\ r \ n。至少前兩條換行符爲我解決了「標題部分超過10240字節(可能沒有正確終止)」的問題。

而這個代碼不看起來是正確的:

postData += "myId=123&someFk=456"; 

我爲此我使用和iPhone應用程序的Objective-C代碼的工作,現在看起來是這樣的:

NSMutableData *reqData = [NSMutableData data]; 
NSURL *encUrl; 
encUrl = [NSURL URLWithString:[NSString url]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:encUrl]; 
request.HTTPMethod = @"POST"; 
request.timeoutInterval = kServerConnectionTimeout; 
    NSString *stringBoundary = [NSString stringWithString:@"Multipart-Boundary"]; // TODO - randomize this 
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=\"%@\"",stringBoundary]; 
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; 

[reqData appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
for (id key in [self.parameters allKeys]) 
{ 
    if (![key isEqualToString:@"image"]) 
    { 
     NSString *val = [self.parameters objectForKey:key]; 
     if (val != nil) 
     { 
      [reqData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n",key] dataUsingEncoding:NSUTF8StringEncoding]]; 
      [reqData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
      [reqData appendData:[[NSString stringWithFormat:@"Content-Transfer-Encoding: 8bit\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
      [reqData appendData:[[NSString stringWithFormat:@"%@",val] dataUsingEncoding:NSUTF8StringEncoding]]; 
      [reqData appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     } 
    } 
} 

// send binary part last 
if ([self.parameters objectForKey:@"image"]) 
{ 
    NSString *key = @"image"; 
    NSData *imageData = [self.parameters objectForKey:key]; 
    if (imageData != nil) 
    { 
     [reqData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"image\";filename=\"avatar.png\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [reqData appendData:[[NSString stringWithFormat:@"Content-Type: image/png\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [reqData appendData:[[NSString stringWithFormat:@"Content-Transfer-Encoding: binary\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [reqData appendData:imageData]; 
     [reqData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    } 
} 
NSString * dataLength = [NSString stringWithFormat:@"%d", [reqData length]]; 
[request addValue:dataLength forHTTPHeaderField:@"Content-Length"]; 

request.HTTPBody = reqData; 
NSLog(@"postBody=%@", [[NSString alloc] initWithData:reqData encoding:NSASCIIStringEncoding]); 

希望這有助於有人。