Large Binary (byte []) Передача файлов через WCF - PullRequest
21 голосов
/ 17 мая 2011

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

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

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

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

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

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

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

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

У меня есть точка останова в первой строке метода обслуживания, в случае успешной передачи файла (ниже 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>

Ответы [ 4 ]

17 голосов
/ 17 мая 2011

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

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

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

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

16 голосов
/ 17 мая 2011

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

Использование привязки вот так, обратите внимание на настройки 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 # не работает на момент написания, но другие примеры кода выглядят нормально).

4 голосов
/ 17 мая 2011

Рассматривали ли вы использование потоковой передачи?

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

1 голос
/ 24 мая 2013

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...