Schwierigkeiten bei der Verwendung von WCF für das hochladen von großen Dateien
Gibt es eine Reihe von anderen ähnlichen Fragen auf, SO etwa diese. Leider, viele zu sein scheinen dupes von einander in mancher Hinsicht. Ich hoffe, dass dieser anderen helfen und zur Ruhe setzen andere Fragen.
Mein Projekt erforderlich ist, um 250MB hochladen von Dateien über den IIS in einem backend-WCF-Dienst in IIS gehostet. Ich habe einige unit-tests für die backend-WCF-Dienst in IIS gehostet. Sie sind:
1) Upload 1MB File
2) Upload 5MB File
3) Upload 10MB file
4) Upload 20MB File
5) Upload 200MB File
Rechts von der Fledermaus, es ist wohl klar, dass wir brauchen, um mit irgendeiner Art von streaming oder chunking-Datei übertragen. Ich habe dieses Beispiel.
Das Beispiel beschreibt eine Methode, die verwendet die .NET-Stream-Objekt. Ein Nebeneffekt bei der Verwendung des stream-Objekts, ist, dass müssen Sie verwenden die Message-Verträge. Es ist nicht genug, um den Strom in Ihrer Funktion parameter-Liste. Also tun wir das.
Standardmäßig die web -.config für das WCF service ist ziemlich mager. Und nichts funktioniert:
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
Nach langem suchen und Experimentieren, es ist klar, dass "BasicHttpBinding" ist inkompatibel mit dieser Kombination aus Stream-Objekt und die MessageContract. Müssen wir wechseln "WSHttpBinding".
Dazu, die server-web.config wird etwas Komplex unter der Rubrik:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
</behavior>
<behavior name="FileServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" maxConcurrentInstances="500"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="FileServiceBinding" closeTimeout="10:01:00"
maxBufferPoolSize="104857600"
maxReceivedMessageSize="104857600" openTimeout="10:01:00"
receiveTimeout="10:10:00" sendTimeout="10:01:00"
messageEncoding="Mtom">
<readerQuotas maxDepth="104857600" maxStringContentLength="104857600"
maxArrayLength="104857600" maxBytesPerRead="104857600"
maxNameTableCharCount="104857600" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="FileServiceBehavior" name="OMS.Service.FileService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="FileServiceBinding" contract="OMS.Service.IFileService"></endpoint>
</service>
</services>
</system.serviceModel>
Ohne mehr Arbeit zu sprechen, 1MB Datei sind nun vorbei mit kein problem.
Um Dateien größer als 4MB zu übergeben, haben Sie zum anpassen einer Einstellung in der web.config im IIS (server-Seite der WCF-service) Dieser Artikel von Microsoft erklärt, was, die Einstellung ist. Zum Beispiel, wenn Sie setzen es auf 8192, dann werden Sie in der Lage, laden Sie die 5MB-Datei, aber nicht alles größer.
<httpRuntime maxRequestLength="8192" />
Ich mir etwas obszön für die Prüfung - 2147483647. Die ersten 4 Dateien übergeben das Tor.
Den 200MB habe nicht die chance bekommen, es zu machen, um das Tor zum nächsten Grund:
System.InsufficientMemoryException: Failed to allocate a managed memory buffer of 279620368 bytes. The amount of available memory may be low. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
Die Erklärung für dieses problem ist sehr gut beschrieben, durch dieses Plakat.
Denken Sie daran, wie diese. Die 200MB Datei nicht aus dem client. Es muss vollständig geladen werden, bis die vom client verschlüsselt und dann zum server übertragen.
Wenn Sie Visual Studio 2010 zum generieren der proxy-Klassen für den service, es packt ein paar Sachen in Ihre app.config. Für mich sieht es so aus:
<binding
name="Binding_IFileService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" />
</security>
</binding>
Der Schlüssel ist die security-Modus. Es ist eingestellt "Meldung" standardmäßig. Dieser Wert nahm von was auch immer auf dem server festgelegt ist. Standardmäßig ist das server-Message-level security.
Wenn Sie versuchen, es zu zwingen auf dem server zu sein:
<security mode="None">
Du diese Fehlermeldung erhalten:
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://localhost:8080/oms/FileService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
(Ich dachte an ein update der client-proxy)
Und so, das ist, wo es steht für mich.... Hilfe!!!
- Keine Antwort für Sie, aber streaming funktioniert mit BasicHttpBinding und Nachricht Verträge. Ohne zu sehen, Ihre .config auf, dass die Bühne, ich konnte nicht sagen, was die Ursache Ihrer 400 obwohl...
- Dies ist nicht wirklich eine Antwort, aber wenn ich Probleme mit meiner Bindung und endpoint-Konfigurationen, die ich ein tool verwenden, das in VS2010 zu helfen, machen Sie das XML-ein bisschen weniger verwirrend. Gehen Sie zu "Tools" -> "WCF Service Configuration Editor". Sie können Sie verwenden, um Bearbeiten Sie sowohl Ihre client-und host-Konfiguration. Wie bereits erwähnt, in einer Antwort, beide müssen übereinstimmen, sonst erhalten Sie endpoint nicht gefunden Fehler oder Sicherheit Fehler. BTW, schöne ausführliche Frage!
- Keine Antwort. Wie kommt man dazu für ein NetTcpBinding? Ich möchte nicht, dass ein dup Frage... irgendwelche Ideen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
WCF in der Regel nicht mit großen Dateiübertragungen gut, es sei denn, Sie implementieren streaming, die tatsächlich erreicht werden, mit BasicHttpBindings.
Für mein Projekt, habe ich eine benutzerdefinierte host-Fabrik, die schafft service-hosts:
Möchten Sie StreamedRequest in Ihrem Fall.
Sowie die Umsetzung der StreamingService:
Ich nicht angeben, eine maximale Puffergröße in den Dienst selbst, sondern in der client-Anwendung, in meinem Fall der download gedrosselt, um so etwas wie 5 MB die Sekunde. In Ihrem Fall, der Dienst selbst muss die Drosselklappe Verhalten. Dies löst nicht das Problem, wie Sie sagen, der service, wie viele bytes in die Datei, um zu streamen, richtig, aber es sollte Ihnen beginnen.
Sollten Sie auch beachten Sie die Verwendung von MTOM in der host-Konfiguration. MTOM wurde entwickelt, um mit der übertragung von großen Dateien (nicht so toll für kleine transfers).
Habe ich nicht ein Beispiel für das client-Verhalten, aber Ihr service Lesen sollten, die Anzahl der bytes, die von der upload-stream-Puffer und speichern Sie diese Datei, bis nichts mehr übrig ist, um zu streamen. Obwohl der Speicher Billig ist, würde ich nicht empfehlen die Aufbewahrung einer kompletten in-memory-Kopie der Datei, insbesondere bei 200mb.
Sollten Sie sich auch bewusst sein, dass abhängig von Ihrem web-hosting-Plattform (IIS, Apache etc.) Sie kann auch begrenzt werden, um die Menge der Daten, die übertragen werden können, zu einer bestimmten Zeit. Jedoch eine änderung in der Konfiguration können in der Regel beheben Sie alle hosting-Probleme.
Ich hoffe, das hilft.
Schöne ausführliche Frage 🙂
Ihre Letzte Fehlermeldung 404-Datei nicht gefunden. In der Regel ist dies, dass die Datei fehlt oder die Seite ist down. Überprüfen Sie dies nur, um dies auszuschließen.
Basierend auf der letzten änderung, die Sie deaktiviert haben messaged basierte Verschlüsselung. Diese änderung muss auf dem client und dem server. Wenn eine Seite ist die Verschlüsselung und der andere nicht erwarten, dass die Nachricht verschlüsselt werden soll, kommt er Durcheinander.
Ist es möglich, Dateien zu komprimieren?, ich weiß, dass ist keine Lösung, aber es kann helfen, wenn Sie wissen, die maximale Größe, die unterstützt werden.
Wenn nicht der einzige Weg, um streaming-Datei oder aufgeteilt in mehrere Stücke.