TL; DR: Wie kann ich große Dateien mit einer bekannten Größe mit WCF streamen, und weiterhin Fortschritt (Content-Length
) an den Endbenutzer (ein Webbrowser)?Übertragung von großen Dateien: Kombination von Streaming-Übertragung und Content-Länge
Ich habe einen WCF REST Service, der sehr große Dateien (1-20Gb) herunterlädt und dann an einen Webbrowser liefert. Um zu vereinfachen, denke an meinen Dienst als Stellvertreter. Dies zwingt mich, TransferMode = Streamed
oder TransferMode = StreamedResponse
auf der Bindung, oder der End-Client muss warten, bis die Quelldateien auf den Webserver heruntergeladen werden, bevor der eigentliche Download beginnt. Außerdem wird durch den gepufferten Übertragungsmodus der Server für große Dateien (RAM-Auslastung) beendet. Zwischenplattenspeicher ist keine Option. Von TransferMode Manpage:
(...) Buffered Transfers halten Sie die gesamte Nachricht in einem Speicherpuffer bis die Übertragung abgeschlossen ist.
Aber wenn TransferMode
zu Streamed
oder StreamedResponse
Einstellung WCF nicht mehr gibt den Header Content-length
an den Client, und ein neuer Header Transfer-Encoding: chunked
hinzugefügt wird. Dies steht im Einklang mit wikipedias article auf segmentierte Übertragungs:
(...) verwendet den Transfer-Encoding HTTP-Header anstelle des Content-Length-Header (...)
Aber Ich weiß immer die Größe der Daten, die vorher übertragen werden müssen, und für den Endbenutzer ist es sehr frustrierend, die Größe des Downloads nicht zu kennen. Also:
(Wie) kann ich die WCF-Bindung zu verwenden, um einen „Streaming“ Transfer-Modus konfigurieren (genauer gesagt nicht die gesamte Nachricht Pufferung vor dem Senden) und immer noch die Content-Length
Header verwenden?
Einige Leitungen:
This q/a besagen, dass der HTTP-Standard sowohl
Transfer-Encoding
undContent-length: 123456
in der gleichen Nachricht nicht zulässt, so dass ich denke, dass nicht eine Option?Ich habe versucht, die Header modifizieren einen Inspektor in IDispatchMessage.BeforeSendReply aber an dieser Stelle die
Content-Length
Header entfernt wurde noch nicht verwendet wird, undTransfer-Encoding
noch nicht gesetzt worden ist, so ist es „zu früh“. Ich habe später gelesen, dass Chunked-Transfer-Codierung auf TCP-Ebene ist, so dass das Ändern des Headers zu diesem Zeitpunkt wahrscheinlich nicht funktionieren wird, selbst wenn ich könnte.Ich habe versucht Einstellung aspNetCompatibilityEnabled
="true"
, Einstellung von wcf Übertragungsmodus auf gepufferte Ausgabe (Standard) und dannSystem.Web.HttpContext.Current.Response.BufferOutput = false;
. Dies wird jedoch von der wcf ignoriert, die Nachricht ist eindeutig gepuffert.Es scheint eine fehlende Funktion zu sein, nach this link. Aber es kann immer noch eine schrullige Workaround irgendwo sein ..
leider, wie in der Frage angegeben (ich betone das etwas, so dass es klarer ist), ist der Client ein Webbrowser. Jede Umgehung auf der Client-Seite müsste daher JavaScript oder einen anderen browser-verfügbaren Trick verwenden. Obwohl, wenn jemand "Nein" auf meine Frage antwortet, muss ich möglicherweise einen benutzerdefinierten Downloader betrachten, der wahrscheinlich so aussieht wie Ihre Antwort. – Tewr