Передача больших двоичных файлов (байт []) через WCF
Я пытаюсь создать службу WCF, которая позволяет мне отправлять большие двоичные файлы с клиентов в службу.
однако я могу успешно передавать файлы только до 3-4MB. (Я терплю неудачу, когда пытаюсь передать 4.91 MB и, конечно, что-нибудь за его пределами)
ошибка, которую я получаю, если я пытаюсь отправить файл 4.91 MB:
Сообщение Об Исключении: произошла ошибка при получении ответа HTTP на http://localhost:56198/Service.svc. Это может быть связано с привязкой конечной точки службы, не использующей протокол HTTP. Это также может быть связано с тем, что контекст HTTP-запроса прерывается сервером (возможно, из-за отключения службы). Дополнительные сведения см. В разделе журналы сервера.
Сообщение О Внутреннем Исключении: базовое соединение закрыто: непредвиденная ошибка при приеме.
Сообщение О Внутреннем Исключении: не удалось прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным узлом.
Сообщение О Внутреннем Исключении: существующее соединение было принудительно закрыто удаленным узлом
эта ошибка возникает на стороне клиента, как только файл byte[] отправляется в качестве параметра метода в открытый метод службы.
у меня есть точка останова в первой строке метода службы, в случае успешной передачи файлов (ниже 3 МБ), которые ломаются точка попадает и файл передается. Однако в этом случае, как только вызывается метод, возникает ошибка. Точка останова в службе не попадает в случае этой ошибки.
Я собираюсь вставить мои разделы моей веб-службы.config и Asp страница (клиент) Web.конфиг. Если вам также требуется код, который отправляет файл и принимает файл, дайте мне знать, я отправлю его.
Сервис 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>
Клиент (Asp.net страница) веб.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 ответов
(хотя я согласен, что потоковой передачи было бы предпочтительнее, ниже должно работать без каких-либо других изменений)
вам также необходимо увеличить максимальную длину сообщения в Интернете.config:
<configuration>
<system.web>
<httpRuntime maxMessageLength="409600"
executionTimeoutInSeconds="300"/>
</system.web>
</configuration>
это установит максимальную длину сообщения до 400 МБ (параметр находится в КБ). Проверка эта страница MSDN для получения дополнительной информации.
как указано, попробуйте использовать Потоковой Передачи, вот пример кода, показывающий как отправку, так и получение (возможно) больших объемов данных с использованием потоковой передачи.
использовать обязательные вот так, Обратите внимание на MaxReceivedMessageSize
и TranferMode
настройки.
<binding name="Streaming_Binding" maxReceivedMessageSize="67108864"
messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed">
</binding>
добавить сервис код:
[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();
}
и клиентский код:
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));
}
кроме того, убедитесь, что вы не получаете таймаут, большой файл может занять некоторое время для передачи (по умолчанию receiveTimeout составляет 10 минут).
вы можете скачать пример кода Microsoft WCF/WF здесь (верхняя ссылка C# сломана во время написания, но другие примеры кода кажутся ОК).
вы посмотрели на использование потоковой передачи?
Windows Communication Foundation (WCF) может отправлять сообщения, используя буферизацией или потоковая передача. В режим буферизации по умолчанию, a сообщение должно быть полностью доставлено прежде чем получатель сможет прочитать его. В потоковый режим передачи, приемник может начать обработку сообщения прежде чем он будет полностью доставлен. Этот режим потоковой передачи полезен, когда информация, которая передается длинный и может обрабатываться последовательно. Режим потоковой передачи также полезен, когда сообщение слишком велико, чтобы быть полностью буферизованный.
Я повторю то, что говорили другие, и скажу, что использование потоковой передачи-это путь при использовании Windows Communication Foundation. Ниже приведено отличное руководство, которое объясняет все шаги для потоковой передачи файлов через WCF. Она достаточно полная и очень информативная.
вот это: руководство по потоковой передаче файлов через WCF.