Подтвердить что ты не робот

Большой двоичный файл (байт []) Передача файла через WCF

Я пытаюсь создать службу WCF, которая позволяет мне отправлять большие двоичные файлы от клиентов к службе.

Однако я могу только успешно передавать файлы до 3-4 МБ. (Я терпеть неудачу, когда пытаюсь передать 4.91MB и, конечно, что-то за пределами)

Ошибка, которую я получаю, если попытаюсь отправить файл 4.91MB:

Сообщение об исключении: Произошла ошибка при получении ответа HTTP на http://localhost:56198/Service.svc. Это может быть связано с привязкой конечной точки службы, не использующей протокол HTTP. Это также может быть связано с тем, что сервер HTTP-запроса прерывается, и, возможно, из-за отключения службы. Подробнее см. Журналы сервера.

Внутреннее сообщение об исключении: Подключенное соединение было закрыто: произошла непредвиденная ошибка при приеме.

Внутреннее сообщение об исключении: Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом.

Внутреннее сообщение об исключении: существующее соединение было принудительно закрыто удаленным хостом

Эта ошибка возникает на стороне клиента, как только файл byte [] отправляется как параметр метода в открытый метод службы.

У меня есть точка останова в первой строке метода обслуживания, в случае успешной передачи файлов (ниже 3 МБ), что точка прерывания попадает и файл передается. Однако в этом случае, как только вызывается метод, возникает ошибка. Точка останова в сервисе не будет удалена в случае этой ошибки.

Я собираюсь вставлять разделы моего сервиса Web.config и Asp Page (Client) Web.config. Если вы также нуждаетесь в коде, который отправляет файл и принимает файл, сообщите мне, я также отправлю его.

Сервис 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) 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>
4b9b3361

Ответ 1

(Хотя я согласен с тем, что потоковая передача будет предпочтительной, ниже должно заставить ее работать без каких-либо изменений)

Вам также необходимо увеличить максимальную длину сообщения в Web.config:

<configuration>
  <system.web>
  <httpRuntime maxMessageLength="409600"
    executionTimeoutInSeconds="300"/>
  </system.web>
</configuration>

Это установит максимальную длину сообщения до 400 МБ (параметр находится в kB). Для получения дополнительной информации просмотрите эту страницу MSDN.

Ответ 2

Как указано, попробуйте использовать Streaming Transfer, здесь приведен пример кода, показывающего как отправку, так и получение (возможно) больших объемов данных с использованием потоковой передачи.

Используйте привязку , как это, обратите внимание на настройки 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));
}

Кроме того, убедитесь, что вы не получаете тайм-аут, большой файл может потребоваться некоторое время для передачи (по умолчанию getTimeout составляет 10 минут).

Вы можете загрузить кучу кода примера Microsoft WCF/WF здесь.

Ответ 3

У вас был взгляд на использование Streaming Transfer?

Windows Communication Foundation (WCF) может отправлять сообщения, используя буферизованные или потоковые передачи. в режим буферизации по умолчанию, сообщение должно быть полностью доставлено прежде чем получатель сможет его прочитать. В потоковый режим передачи, приемник может начать обрабатывать сообщение прежде чем он будет полностью доставлен. потоковый режим полезен, когда информация, которая передается, является длинной и может обрабатываться последовательно. Режим потоковой передачи также полезен, когда сообщение слишком велико, чтобы быть полностью буфер.

http://msdn.microsoft.com/en-us/library/ms789010.aspx

Ответ 4

Я повторю то, что говорили другие, и скажу, что использование Streaming Transfer - это путь, который можно использовать при использовании Windows Communication Foundation. Ниже приведено превосходное руководство, в котором объясняются все шаги для потоковой передачи файлов по WCF. Это довольно всеобъемлющий и очень информативный.

Вот он: Руководство по потоковым файлам через WCF.