无法跨域传递大量数据

Posted

技术标签:

【中文标题】无法跨域传递大量数据【英文标题】:Unable to pass large amount of data cross domain 【发布时间】:2014-06-29 17:57:57 【问题描述】:

我在我的 c# mvc 应用程序中使用 wcf 服务。我需要通过 wcf 到客户端(到控制器)获取大量数据(大约 20000 条记录)。

在本地版本中 - 我可以很好地获取所有记录,但在服务器版本中,如果我不将查询限制为 1000 条记录,我将一无所获。

当它不受限制并试图带来所有记录时,这就是我在客户端日志中得到的:

System.ServiceModel.CommunicationException:发生错误时 接收对 xxx/WCF.svc 的 HTTP 响应。这可能是由于 到不使用 HTTP 协议的服务端点绑定。这 也可能是由于 HTTP 请求上下文被 服务器(可能是由于服务关闭)。查看服务器日志 更多细节。 ---> System.Net.WebException:底层 连接已关闭:接收时发生意外错误。 ---> System.IO.IOException:无法从传输中读取数据 连接:已存在的连接被远程强行关闭 主持人。 ---> System.Net.Sockets.SocketException:现有连接 被远程主机强行关闭 System.Net.Sockets.NetworkStream.Read(Byte[] 缓冲区,Int32 偏移量, Int32 大小)---内部异常堆栈跟踪结束---在 System.Net.Sockets.NetworkStream.Read(Byte[] 缓冲区,Int32 偏移量, Int32 大小)在 System.Net.PooledStream.Read(Byte[] 缓冲区,Int32 偏移量,Int32 大小)在 System.Net.Connection.SyncRead(HttpWebRequest 请求,布尔值 userRetrievedStream, Boolean probeRead) --- 内部异常结束 堆栈跟踪 --- 在 System.Net.HttpWebRequest.GetResponse() 在 System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) --- 内部异常堆栈跟踪结束 ---

我已将此添加到客户端的 web.config 中,但没有帮助:

<behaviors>
      <endpointBehaviors>
        <behavior >
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>

有什么想法吗?

【问题讨论】:

服务器端的 WCF 跟踪是否显示任何错误? 你为什么不只使用分页并一次请求说 1000 个项目?一次获取所有内容可以说是一个糟糕的设计选择。这是通过 Internet 还是仅仅通过公司 LAN?您仍然可以使用 tcp 进行跨域。如果它是一个局域网,你应该使用 tcpBinding。 J. Lowy,“编程 WCF 服务”,第 3 版 【参考方案1】:

您的绑定配置是否设置为允许大数据? 如果您使用的是 httpbinding,您应该以这种方式配置您的端点和服务

<basicHttpBinding>
<binding name="LargeDataBindingConfiguration" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false">
<readerQuotas maxDepth="32" maxStringContentLength="998192" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>

然后尝试在您的服务器上增加 IIS 支持的请求中内容的最大长度

<security>
    <requestFiltering>
        <requestLimits maxAllowedContentLength="4294967295" />
    </requestFiltering>
</security>

【讨论】:

虽然这是一个很好的答案,但它通过隐藏症状而不是修复原因来鼓励不良做法 - 在这种情况下,OP 的糟糕设计是一次获取所有内容而不是使用分页。【参考方案2】:

正如 Mackho 所说,您应该在第一个配置设置中增加超时时间。此外,客户端必须增加他们的超时值和他们可以从服务器获得的最大内容。

另外,如果您确实需要传递所有数据并且不想使用分页,则可以使用流式传输服务。要将您的服务配置为以流模式运行,请添加:

<bindings>
     <basicHttpBinding>
        <binding transferMode="Streamed" name="LargeDataBindingConfiguration" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false">
        <readerQuotas maxDepth="32" maxStringContentLength="998192" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647" />
        </binding>
    </basicHttpBinding>
</bindings>

请注意,您的客户端设置也很重要:

以最低超时为准(来自客户端或服务器) 以 maxStringContentLength 与客户端关于他们可以接收多少的设置之间的最低值为准 要使用流式传输,客户端必须支持它并且也具有相同的设置(否则,在客户端上数据将被缓冲)

这真的取决于异常是由服务器还是由客户端抛出的。在两者中启用 WCF 跟踪并查看引发异常的位置,然后在该端进行必要的配置。

【讨论】:

以上是关于无法跨域传递大量数据的主要内容,如果未能解决你的问题,请参考以下文章

localstorage

在网页之间传递大量数据

在 PHP 和 Perl 之间传递大量数据

如何使用数据库将大量数据从一个活动传递到android中的另一个活动

向控制器传递大量参数?

页面间大量数据参数传递