22

クライアントからサービスに大きなバイナリ ファイルを送信できる WCF サービスを構築しようとしています。

ただし、最大 3 ~ 4 MB のファイルしか正常に転送できません。(4.91MB を転送しようとすると失敗します。もちろん、それ以上のものは転送できません)

4.91MB のファイルを送信しようとすると、次のエラーが表示されます。

例外メッセージ: http://localhost:56198/Service.svcへの HTTP 応答の受信中にエラーが発生しました。これは、サービス エンドポイント バインディングが HTTP プロトコルを使用していないことが原因である可能性があります。これは、HTTP 要求コンテキストがサーバーによって中止されたことが原因である可能性もあります (サービスのシャットダウンが原因である可能性があります)。詳細については、サーバー ログを参照してください。

内部例外メッセージ:基になる接続が閉じられました: 受信時に予期しないエラーが発生しました。

内部例外メッセージ:トランスポート接続からデータを読み取ることができません: 既存の接続がリモート ホストによって強制的に閉じられました。

内部例外メッセージ:既存の接続がリモート ホストによって強制的に閉じられました

このエラーは、公開されたサービス メソッドにメソッド パラメータとして byte[] ファイルが送信されるとすぐに、クライアント側で発生します。

サービス メソッドの最初の行にブレークポイントがあります。ファイル転送が成功した場合 (3MB 未満)、ブレーク ポイントにヒットしてファイルが転送されます。ただし、この場合、メソッドが呼び出されるとすぐにエラーが発生します。このエラーの場合、サービスのブレークポイントはヒットしません。

Service 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

4 に答える 4

18

(ストリーミング転送が望ましいことに同意しますが、以下は他の変更なしで機能するはずです)

また、Web.config でメッセージの最大長を増やす必要があります。

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

これにより、メッセージの最大長が 400 MB に設定されます (パラメーターは kB 単位です)。詳細については、この MSDN ページを確認してください。

于 2011-05-17T11:43:28.473 に答える
18

指摘したように、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));
}

また、タイムアウトが発生していないことを確認してください。大きなファイルは転送に時間がかかる場合があります (ただし、デフォルトの receiveTimeout は 10 分です)。

ここからMicrosoft WCF/WF のサンプル コードをダウンロードできます(執筆時点ではトップの C# リンクは壊れていますが、他のサンプル コードは問題ないようです)。

于 2011-05-17T11:55:09.427 に答える
5

Streaming Transfer の使用を検討しましたか?

Windows Communication Foundation (WCF) は、バッファー転送またはストリーミング転送を使用してメッセージを送信できます。デフォルトの buffered-transfer モードでは、受信者がメッセージを読み取る前にメッセージが完全に配信される必要があります。ストリーミング転送モードでは、メッセージが完全に配信される前に、受信者がメッセージの処理を開始できます。ストリーミング モードは、渡される情報が長く、連続して処理できる場合に便利です。ストリーミング モードは、メッセージが大きすぎて完全にバッファリングできない場合にも役立ちます。

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

于 2011-05-17T11:41:33.183 に答える
2

Windows Communication Foundation を使用する場合は、ストリーミング転送を使用するのが最善の方法であると他の人が言ったことを繰り返します。以下は、WCF 経由でファイルをストリーミングするためのすべての手順を説明する優れたガイドです。それは非常に包括的で非常に有益です。

ここにあります:WCFを介したファイルのストリーミングに関するガイド

于 2013-05-23T20:47:19.313 に答える