Transfert de gros fichiers binaires (byte[]) par WCF
j'essaie de construire un service WCF qui me permet d'envoyer de gros fichiers binaires des clients au service.
cependant, je ne suis capable de transférer avec succès des fichiers jusqu'à 3-4MB. (Je ne lorsque j'essaie de transférer 4.91 MO et, bien sûr, quelque chose au-delà)
L'Erreur que j'obtiens si j'essaie d'envoyer le 4.91 MO fichier est:
Message D'Exception: une erreur s'est produite lors de la réception de la réponse HTTP à http://localhost:56198/Service.svc. Cela pourrait être dû au fait que le protocole HTTP n'est pas utilisé pour lier les points de service. Cela pourrait également être dû à un contexte de requête HTTP avorté par le serveur (peut-être en raison de la fermeture du service). Voir les journaux du serveur pour plus de détails.
Inner Exception Message: La connexion sous-jacente a été fermée: Une erreur inattendue s'est produite sur une recevoir.
Inner Exception Message: Impossible de lire les données de la connexion de transport: Une connexion existante a dû être fermée par l'hôte distant.
Inner Exception Message: Une connexion existante a dû être fermée par l'hôte distant
cette erreur se produit côté client dès que le fichier byte[] est envoyé comme paramètre de méthode à la méthode de service exposée.
j'ai un point de rupture à la première ligne de la méthode de service, en cas de transferts de fichiers réussis (moins de 3MB) qui se casse point est atteint et que le fichier est transféré. Toutefois, dans ce cas, dès que la méthode est appelée, vient l'erreur. Le point de rupture du service n'est pas touché en cas d'erreur.
je vais coller mes sections de mon service Web.page Web de config et Asp (Client).config. Si vous avez besoin du code d'envoyer le fichier et accepte le fichier, faites le moi savoir, je vais vous les envoyer.
Service Web.Config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpEndpointBinding" closeTimeout="01:01:00"
openTimeout="01:01:00" receiveTimeout="01:10:00" sendTimeout="01:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483646" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="StreamedRequest"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646"
maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="DragDrop.Service.ServiceBehavior" name="DragDrop.Service.Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpEndpointBinding" contract="DragDrop.Service.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DragDrop.Service.ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client (Asp.net la page Web).Config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483646" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="StreamedResponse"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646"
maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="debuggingBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:56198/Service.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference.IService"
name="BasicHttpBinding_IService" behaviorConfiguration="debuggingBehaviour" />
</client>
</system.serviceModel>
4 réponses
transfert de streaming serait préférable, ci-dessous devrait le faire fonctionner sans les autres modifications)
vous devez également augmenter la longueur maximale des messages dans le Web.config:
<configuration>
<system.web>
<httpRuntime maxMessageLength="409600"
executionTimeoutInSeconds="300"/>
</system.web>
</configuration>
cette option permet de régler la longueur maximale du message à 400 Mo (le paramètre est en Ko). Vérifier cette page MSDN pour plus d'informations.
comme indiqué, essayez Transfert De Streaming, voici un exemple de code montrant à la fois l'envoi et la réception (éventuellement) de grandes quantités de données en utilisant le transfert en continu.
un liaison comme ceci, notez le MaxReceivedMessageSize
et TranferMode
paramètres.
<binding name="Streaming_Binding" maxReceivedMessageSize="67108864"
messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed">
</binding>
Ajouter quelques code de service:
[OperationContract]
public Stream GetLargeFile()
{
return new FileStream(path, FileMode.Open, FileAccess.Read);
}
[OperationContract]
public void SendLargeFile(Stream stream)
{
// Handle stream here - e.g. save to disk
ProcessTheStream(stream);
// Close the stream when done processing it
stream.Close();
}
Et certains code client:
public Stream GetLargeFile()
{
var client = /* create proxy here */;
try
{
var response = client.GetLargeFile();
// All communication is now handled by the stream,
// thus we can close the proxy at this point
client.Close();
return response;
}
catch (Exception)
{
client.Abort();
throw;
}
}
public void SendLargeFile(string path)
{
var client = /* create proxy here */;
client.SendLargeFile(new FileStream(path, FileMode.Open, FileAccess.Read));
}
Aussi, assurez-vous que vous n'obtenez pas une timeout, un gros fichier peut prendre un certain temps à transférer (par défaut, receiveTimeout est de 10 minutes).
vous pouvez télécharger le code D'échantillon Microsoft WCF/WF ici (le lien C# du haut est cassé au moment de l'écriture mais le code des autres samples semble ok).
avez-vous examiné l'utilisation du transfert en continu?
Windows Communication Foundation (WCF)) vous pouvez envoyer des messages en utilisant soit transfert tamponné ou strié. Dans le mode de transfert tamponné par défaut, a le message doit être livré en entier avant qu'un récepteur puisse les lire. Dans mode de transfert en continu, le récepteur peut commencer à traiter le message avant d'être complètement remis. Le le mode streaming est utile lorsque le l'information qui est transmise est long et peut être traitée en série. Le mode Streaming est également utile lorsque le le message est trop volumineux pour être entièrement mise en mémoire tampon.
je vais faire écho à ce que d'autres ont dit et dire que l'utilisation d'un transfert en continu est la voie à suivre lorsque vous utilisez Windows Communication Foundation. Ci-dessous est un excellent guide qui explique toutes les étapes afin de streamer des fichiers sur WCF. C'est assez complet et très instructif.
la Voici: Guide sur la diffusion des fichiers sur WCF.