0

Ich versuche, eine Multipart-Anfrage an eine Web-API mit HttpWebRequest zu senden. Die Anfrage Ich schicke hat folgendes Format:Multipart-Anfrage von Web-API abgelehnt

----------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} 

Und die Anfrage Konfiguration ist wie folgt:

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

Wenn die Anforderung an den Web-API sendet ich die Invalid end of stream error bekommen. Allerdings habe ich versucht, den Stream in Text umzuwandeln, um die tatsächlichen Daten zu sehen, und es stimmt mit dem Beispiel überein, das ich oben hinzugefügt habe.

Wenn ich jedoch die WebClient verwenden und die UploadFile Methode für den gleichen Zweck aufrufen, kann ich erfolgreich Dateien auf die API ohne Probleme vorschlagen, was darauf hindeutet, dass etwas mit meinem Ansatz falsch ist, der wie folgt ist.

Meine Konstanten:

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"); 

Verfahren zur Datenformatierung Form:

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)); 

Datei anhängen zu einem Strom:

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; 

Erstellen der Anfrage:

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; 
    } 

Antwort

2

Sie haben nicht in Ihrer Frage die BoundaryDelimiter Variablendeklaration aber für die Zwecke dieser Antwort gezeigt Ich gehe davon aus, dass es wie folgt definiert ist:

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

Jetzt ist das Problem mit Ihrem Code, dass Sie ein paar Bindestriche (--) bei der Berechnung Ihrer Begrenzungszeichen fehlen, um RFC2388 zu entsprechen.

Also statt:

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

Sie müssen dies:

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

Beachten Sie die zusätzlichen --, das ich euren beginnen und enden Inhalt Randbegrenzungszeichen hinzugefügt haben.

Überprüfen Sie das Beispiel 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-- 

Beachten Sie, wie die Grenze zu AaB03x gleich ist, aber das Trennzeichen ist eigentlich --AaB03x und natürlich die Endebegrenzers ist --AaB03x--.

Als Seite beachten Sie loswerden der ContentLenght Variable bekommen konnte (was man :-) durch die Art und Weise falsch geschrieben haben), und entfernen Sie diese Zeile:

request.ContentLength = ContentLenght 

Dieser Code als HttpWebRequest Klasse vereinfacht werden füllt automatisch den Header Content-Length abhängig von der Anzahl der Bytes, die Sie in den Anforderungsstream geschrieben haben.

Dies gesagt, ich würde Ihnen empfehlen, die HttpClient Klasse anstelle von HttpWebRequest zu verwenden, weil es bereits eingebaute Funktionen für die ordnungsgemäße Codierung dieser Art von Sachen hat. Es wird definitiv Ihren Code lesbarer machen, da Sie sich nicht um Grenzen, Trennzeichen und Inhaltslängen kümmern müssen.

+0

Ich habe gerade diese Momente bemerkt, bevor ich deine Antwort sah. :) – Arrrr