简体   繁体   English

大二进制(byte [])通过WCF传输文件

[英]Large Binary (byte[]) File transfer through WCF

I am trying to build a WCF service that allows me to send large binary files from clients to the service. 我正在尝试构建一个WCF服务,允许我从客户端向服务发送大型二进制文件。

However I am only able to successfully transfer files up to 3-4MB. 但是我只能成功传输高达3-4MB的文件。 (I fail when I try to transfer 4.91MB and, off course, anything beyond) (当我尝试转移4.91MB时,我失败了,当然,除了之外)

The Error I get if I try to send the 4.91MB file is: 如果我尝试发送4.91MB文件,我得到的错误是:

Exception Message: An error occurred while receiving the HTTP response to http://localhost:56198/Service.svc . 异常消息:接收到http:// localhost:56198 / Service.svc的HTTP响应时发生错误。 This could be due to the service endpoint binding not using the HTTP protocol. 这可能是由于服务端点绑定不使用HTTP协议。 This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). 这也可能是由于服务器中止HTTP请求上下文(可能是由于服务关闭)。 See server logs for more details. 请参阅服务器日志以获取更多详

Inner Exception Message: The underlying connection was closed: An unexpected error occurred on a receive. 内部异常消息:基础连接已关闭:接收上发生意外错误。

Inner Exception Message: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. 内部异常消息:无法从传输连接读取数据:远程主机强制关闭现有连接。

Inner Exception Message: An existing connection was forcibly closed by the remote host 内部异常消息:远程主机强制关闭现有连接

This error occurs at client side as soon as the byte[] file is sent as a method parameter to the exposed service method. 一旦将byte []文件作为方法参数发送到公开的服务方法,就会在客户端发生此错误。

I have a breakpoint at the service method's first line, in case of successful file transfers (below 3MB) that break point is hit and the file gets transferred. 我在服务方法的第一行有一个断点,如果文件传输成功(低于3MB),则会触发断点并传输文件。 However in this case as soon as the method is called, the error comes. 但是在这种情况下,只要调用该方法,就会出现错误。 The breakpoint in the service is not hit in case of this error. 如果出现此错误,则不会触发服务中的断点。

I am going to paste my sections of my Service Web.config and Asp Page (Client) Web.config. 我将粘贴我的Service Web.config和Asp Page(Client)Web.config的各个部分。 If you also require the code that send the file and accepts the file, let me know, I'll send that as well. 如果您还需要发送文件并接受文件的代码,请告诉我,我也会发送该文件。

Service 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>

Client (Asp.net page) Web.Config 客户端(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>

(While I agree that streaming transfer would be preferrable, the below should make it work without any other changes) (虽然我同意流媒体转移是可取的,但下面的内容应该可以让它在没有任何其他变化的情况下工作)

You also need to increase the maximum message length in the Web.config: 您还需要在Web.config中增加最大消息长度:

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

This will set the maximum message length to 400 MB (parameter is in kB). 这会将最大消息长度设置为400 MB(参数以kB为单位)。 Check this MSDN page for more information. 有关更多信息,请查看此MSDN页面

As pointed out, try using Streaming Transfer , here's some example code showing both sending and receiving (possibly) large amounts of data using streamed transfer. 正如所指出的,尝试使用Streaming Transfer ,这里有一些示例代码,显示使用流传输发送和接收(可能)大量数据。

Use a binding like this, notice the MaxReceivedMessageSize and TranferMode settings. 使用这样的绑定 ,请注意MaxReceivedMessageSizeTranferMode设置。

<binding name="Streaming_Binding" maxReceivedMessageSize="67108864"  
    messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed">
</binding>

Add some service code : 添加一些服务代码

[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();
}

And some client code : 还有一些客户端代码

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));
}

Also, make sure you are not getting a timeout, a large file might take a while to transfer (the default receiveTimeout is 10 minutes though). 此外,请确保您没有超时,大文件可能需要一段时间才能传输(默认的receiveTimeout为10分钟)。

You can download Microsoft WCF/WF sample code here (top C# link is broken at the time of writing but other samples code seems ok). 您可以在此处下载Microsoft WCF / WF示例代码(在编写本文时,顶部C#链接已断开,但其他示例代码似乎没问题)。

Have you had a look at using Streaming Transfer? 你有没有看过使用Streaming Transfer?

Windows Communication Foundation (WCF) can send messages using either buffered or streamed transfers. Windows Communication Foundation(WCF)可以使用缓冲或流式传输发送消息。 In the default buffered-transfer mode, a message must be completely delivered before a receiver can read it. 在默认的缓冲传输模式中,必须在接收器可以读取之前完全传递消息。 In streaming transfer mode, the receiver can begin to process the message before it is completely delivered. 在流传输模式中,接收器可以在完全传递之前开始处理该消息。 The streaming mode is useful when the information that is passed is lengthy and can be processed serially. 当传递的信息很长并且可以连续处理时,流模式很有用。 Streaming mode is also useful when the message is too large to be entirely buffered. 当消息太大而无法完全缓冲时,流模式也很有用。

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

I'll echo what others have said and say that using a Streaming Transfer is the way to go when using Windows Communication Foundation. 我会回应别人的说法并说使用流式传输是使用Windows Communication Foundation时的方法。 Below is an excellent guide that explains all of the steps in order to stream files over WCF. 下面是一个很好的指南,解释了通过WCF流​​式传输文件的所有步骤。 It's quite comprehensive and very informative. 它非常全面,信息量很大。

Here it is: Guide on Streaming Files over WCF . 这是: 通过WCF流​​式传输文件的指南

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM