0

我試圖使用HttpWebRequest向Web API發送多部分請求。我發送請求的格式如下:Web API拒絕了多部分請求

----------636194206488346738 
Content-Disposition: form-data; name="file"; filename="A.png" 
Content-Type:application/octet-stream 
Content-Transfer-Encoding: binary 
{Binary data in here} 
----------636194206488346738-- 
{new line at the end} 

而且要求配置如下:

Content-Type:"multipart/form-data; boundary=----------636194206488346738 
Method: POST 
Keep-Alive: True 

當發送請求到Web API,我得到了Invalid end of stream error。但是,我試圖將流轉換爲文本來查看實際數據,並且它與上面添加的示例相匹配。

但是,當我使用WebClient併爲相同目的調用UploadFile方法時,我可以成功將文件上傳到API,但沒有任何問題表明我的方法出現了問題,如下所示。

我的常量:

Boundary = DateTime.Now.Ticks.ToString(); 
ContentType = "multipart/form-data; boundary=" + BoundaryDelimiter + Boundary; 
BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "\r\n"); 
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "--\r\n"); 

格式化表格數據的方法:

private Byte[] FormDataFormat(String name, String fileName, String contentType) 
     => System.Text.Encoding.UTF8.GetBytes(String.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type:{2}\r\nContent-Transfer-Encoding: binary\r\n\r\n", name, fileName, contentType)); 

附加文件到流:

Stream = new MemoryStream(); 
foreach (var i in files) { 
    var tempEncode = FormDataFormat("file", i, "application/octet-stream"); 
    var file = System.IO.File.ReadAllBytes(i); // Files are supposed to be small. 
    Stream.Write(BeginContent, 0, BeginContent.Length); 
    Stream.Write(tempEncode, 0, tempEncode.Length); 
    Stream.Write(file, 0, file.Length); 
    ContentLenght += BeginContent.Length + tempEncode.Length + file.Length; 
} 
Stream.Write(EndContent, 0, EndContent.Length); 
ContentLenght += EndContent.Length; 

創建要求:

public HttpWebRequest Request(String method) { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
     request.ContentType = ContentType; 
     request.KeepAlive = true; 
     request.Method = method; 
     request.ContentLength = ContentLenght; 
     Stream.Seek(0, SeekOrigin.Begin); 
     Stream.CopyTo(request.GetRequestStream()); 
     Stream.Dispose(); 
     return request; 
    } 

回答

2

你還沒有在你的問題中所示的BoundaryDelimiter變量聲明,但對於這個答案的目的,我會認爲它是這樣定義的:

BoundaryDelimiter = "---------------------" 

現在,您的代碼存在的問題是,在計算邊界分隔符以符合RFC2388時,缺少一對破折號(--)。

所以不是:

BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "\r\n"); 
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "--\r\n"); 

你需要這樣的:

BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + "--" + Boundary + "\r\n"); 
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + "--" + Boundary + "--\r\n"); 

請注意,我已經添加到您的開始和結束邊界的內容分隔符的附加--

檢查例子provided here

Content-Type: multipart/form-data; boundary=AaB03x 

--AaB03x 
Content-Disposition: form-data; name="submit-name" 

Larry 
--AaB03x 
Content-Disposition: form-data; name="files"; filename="file1.txt" 
Content-Type: text/plain 

... contents of file1.txt ... 
--AaB03x-- 

注意的邊界如何等於AaB03x但分隔符實際上是--AaB03x和課程結束分隔符是--AaB03x--

作爲一個側面說明,你可以擺脫ContentLenght變量(您已通過:-)方式拼寫錯誤),並刪除此行:

request.ContentLength = ContentLenght 

這將簡化代碼爲HttpWebRequest類將根據您寫入請求流的字節數自動填充Content-Length標頭。

這就是說,我會建議你使用HttpClient類而不是HttpWebRequest,因爲它已經具有內置功能來正確編碼這種東西。這絕對會讓你的代碼更具可讀性,因爲你不必擔心邊界,分隔符和內容長度。

+0

我剛纔注意到那一刻纔看到你的答案。 :) – Arrrr

相關問題