22

我正在尝试构建一个 WCF 服务,该服务允许我将大型二进制文件从客户端发送到服务。

但是我只能成功传输最大 3-4MB 的文件。(当我尝试传输 4.91MB 时失败了,当然还有其他任何内容)

如果我尝试发送 4.91MB 文件,我得到的错误是:

异常消息:接收对http://localhost:56198/Service.svc的 HTTP 响应时发生错误。这可能是由于服务端点绑定未使用 HTTP 协议。这也可能是由于服务器中止了 HTTP 请求上下文(可能是由于服务关闭)。有关更多详细信息,请参阅服务器日志。

内部异常消息:底层连接已关闭:接收时发生意外错误。

内部异常消息:无法从传输连接读取数据:现有连接被远程主机强制关闭。

内部异常消息:远程主机强制关闭现有连接

只要将 byte[] 文件作为方法参数发送到公开的服务方法,就会在客户端发生此错误。

我在服务方法的第一行有一个断点,以防文件传输成功(低于 3MB),该断点被命中并且文件被传输。但是在这种情况下,只要调用该方法,就会出现错误。如果出现此错误,则不会命中服务中的断点。

我将粘贴我的 Service Web.config 和 Asp Page (Client) 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,这里有一些示例代码显示使用流传输发送和接收(可能)大量数据。

使用这样的绑定,注意MaxReceivedMessageSizeTranferMode设置。

<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

你看过使用流传输吗?

Windows Communication Foundation (WCF) 可以使用缓冲或流传输来发送消息。在默认的缓冲传输模式下,消息必须在接收者可以读取之前完全传递。在流传输模式下,接收方可以在消息完全传递之前开始处理消息。当传递的信息很长并且可以串行处理时,流模式很有用。当消息太大而无法完全缓冲时,流模式也很有用。

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 回答