关于将大字符串发布到 Web 服务的建议
Posted
技术标签:
【中文标题】关于将大字符串发布到 Web 服务的建议【英文标题】:Suggestions on posting huge string to web service 【发布时间】:2017-07-24 15:45:38 【问题描述】:下面是我的数组:
var.child.Cars1 = name:null,operation:0,selected : false
现在在上面的数组中,selected property 表示 check/uncheck status of checkbox 和 我正在使用 json 将上面的数组作为字符串发布到 Web 服务(WCF) .stringify.
上面的数组包含 2000 - 4000 条记录,现在用户可以选中/取消选中复选框。
现在考虑上面数组中有 4000 条记录,其中有 2000 条记录被选中,2000 条记录未被选中,在我的 Web 服务中,我只处理那些被选中的记录。我删除了选定值为 false 的记录。
现在由于有 4000 条记录,它是一个巨大的 json 字符串,因此我从 Web 服务端收到错误:
Error : (413) Request Entity Too Large
现在我之所以不过滤掉选择为 flase 的记录,是因为它会在客户端浏览器上产生大量开销,甚至会挂起浏览器,所以现在我正在服务器端执行此操作。
所以我的问题是我应该在客户端过滤掉选择为 false 的记录,然后只发布 2000 条记录,或者我正在做的是正确的方式。
我有一些疑问,发布如此巨大的 json 字符串将再次花费一些时间,并且过滤掉选择为 false 的记录也会给浏览器带来很多开销。
所以我不确定我做错了还是正确。
有人可以指导我吗???
【问题讨论】:
在客户端过滤掉这个不应该挂起浏览器我想,也许你在用javascript过滤时做错了(效率低下)。无论如何,从两种可能性(在客户端过滤或在服务器上发送无用数据并在那里过滤)我将始终选择客户端上的过滤器。反方向也是如此。 @Evk :好的,如果我认为它不会挂起客户端浏览器,那么这种过滤仍然需要很多时间。考虑如果记录像 7000-8000 那么你仍然会更喜欢这个在客户端? 好吧,除非绝对必须(但无法想象这种情况),否则我永远不会将包含 8000 个项目的数组发布到服务器。你说项目代表复选框状态。我认为用户不能一次手动检查或取消选中 8000 个项目。 Mosy 很可能你向他展示了一个包含 8000 个项目的列表(你至少应该分页)并且他改变了一些。那么 - 仅将已更改的内容发布到服务器,而不是所有项目。 @Evk :我向用户提供了 8000 个项目列表,并且我提供了过滤和选中/取消选中所有选项等功能,用户可以使用该选项选择/取消选择所有项目。使用过滤器用户可以从这些 8000 中过滤项目items.now 考虑用户是否在 checkall 按钮的帮助下选择所有项目?? 然后通知服务器所有项目都已检查,但未列出它们。服务器知道如何获取项目的完整列表。 【参考方案1】:在客户端进行过滤不应产生巨大的开销,并且应该可以将生成的 json
字符串大小维持在请求限制内。
使用underscore.js 非常简单,可以过滤到只选择/检查的元素并映射到只需要的操作:
var filteredCars = _.where(cars, selected: true);
//an assumption that operation is a unique car id
var operations = _.map(filteredCars, function(car) return id: car.operation;);
请参阅此extended JSFiddle 以使用相似的数组大小和旁边的一些统计信息进行过滤。
然而,我怀疑在单个 UI 屏幕中显示 4k 复选框是否对用户友好?
【讨论】:
【参考方案2】:通常,如果您开始遇到这样的大请求大小问题,那么这是一个寻找优化方法而不是覆盖方法的好机会。很多人都尝试过提供规避问题的方法,但没有提供关于不规避问题的方法的见解,而是改进设计以使其更轻量级。
这里有一些可能性:
您是否考虑过分页请求?这将允许您根据需要在客户端上异步加载数据,从而防止请求花费太长时间,提高网站的响应能力,并减少客户端和服务器内存的任何负担。您可以在用户滚动时抢先加载数据,如果需要,如果该过程花费的时间过长,可以向用户提供某种娱乐/反馈,以便他们知道正在加载更多数据。
您是否考虑过将属性名称更改为更短、更少描述性,从而减少对象本身的占用空间?例如:
您当前的型号:
name:null,operation:0,selected : false
简化模型:
n: null, o: 0, s: false
这样的方法会使读取 JSON 本身变得更加困难,但 JSON 不仅仅意味着供人们阅读,它还意味着对数据进行序列化;不过,这可以通过记录您的模型来克服。这样做可能有助于将发送的数据减少多达 30%。
我无法提供完整的解决方案,因为您将不得不问自己很多棘手的问题,例如您要达到什么目标、谁将使用数据以及如何达到目标的最佳方式.
此外,我强烈考虑质疑为什么一个流程需要用户一次与 2000 多条记录进行交互。我不是要批评,而是说您需要批判性地看待您要实现的目标背后的业务流程,因为可能存在重复性、用户压力等严重问题,这将极大地影响您的应用程序将对最终用户有效且有用。例如,有没有办法可以将任务分解成更小、更不乏味的块,以便最终用户不会盯着 4000 个复选框看 2 小时?
这可能不是您要寻找的答案,因为它会引发大量其他问题,但希望它会帮助您开始制定有助于形成最终答案的问题。
【讨论】:
赞成您为帮助我所做的努力。非常好的解释。我非常感谢您的解释。非常感谢,请继续像这样提供帮助:) 不客气。很多时候,我们都面临着快速完成工作的压力,很难不尝试拼凑一些东西,但有时退后一步很重要,尤其是在这种情况下。如果您在尝试确定一个好的解决方案时需要进一步的帮助,请随时提出。 是的,我会的。非常感谢:)【参考方案3】:如果您不影响 UI 线程(锁定浏览器),最好在客户端过滤数据。发布过多数据可能会导致问题,具体取决于您尝试执行的操作以及最终用户的网络速度。话虽如此,有时您只需要发布大量数据。我不确定这 4000 条记录有多大,但如果只是文本,则不能太大。
由于您的问题是 WCF 站点正在响应 413 响应,因此您遇到了最大大小问题。根据WCF documentation,默认情况下可以接收的最大允许消息大小为65,536字节。显然,这低于您尝试发送的内容。
这是您需要在 WCF 服务中更新的内容。下面的示例适用于 10MB,但可以增加到对您的数据有意义的大小。
<system.serviceModel>
<bindings>
<basicHttpBinding>
<!-- Measured in Bytes -->
<binding maxReceivedMessageSize="10485760"> <!-- 10 MB-->
<readerQuotas ... />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
如果您开始收到 404.13 HTTP 状态代码,那么您还需要更新您的 web.config 以允许更长的最大大小,但将其设置为对您的应用程序最有意义的任何大小。
<system.webServer>
<!-- Add this section for file size... -->
<security>
<requestFiltering>
<!-- Measured in Bytes -->
<requestLimits maxAllowedContentLength="1073741824" /> <!-- 1 GB-->
</requestFiltering>
</security>
</system.webServer>
<system.web>
<!-- Measured in kilobytes -->
<httpRuntime maxRequestLength="1048576" /> <!-- 1 GB-->
</system.web>
【讨论】:
我需要在 wcf 和客户端设置 readerquotas 设置对吗? 我只需要在客户端和 wcf 端设置 ReaderQuotas 或者其他配置也可以使这项工作??【参考方案4】:您可以在配置中设置 maxRequestLength。这些设置对我上传 750 mb 有用。
<system.web>
<httpRuntime maxRequestLength="2097151" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
maxRequestLength 最大值是2097151,如果你尝试设置更多的错误发生。 还有MSDN says ;
默认大小为 4096 KB (4 MB)。
【讨论】:
【参考方案5】:如果您使用的是 GET 方法,那么这不起作用,因为 Get 方法 URL 最大字符限制为 2,083 个字符。所以请在使用 Json 对象的 Web 服务中使用 post 方法。
【讨论】:
我对 Web 服务的调用是 Post call 将 json 对象作为字符串传递 var arraylist = []; var jsonList = JSON.stringify(arraylist); var 数据 = 列表:jsonList ;您可以使用 post 方法传递这样的数据。【参考方案6】:您应该在客户端进行过滤,因为您不知道与服务器的连接可能有多慢。发送不需要的数据可能比先过滤要慢。
如果过滤数据导致浏览器挂起,那么您可以使用WebWorker 解决此问题。
【讨论】:
【参考方案7】:快速解决方法可能是增加服务器允许的内容长度。这大概就是它的样子。
<configuration>
<system.web>
<httpRuntime maxRequestLength="2147483647" />
</system.web>
</configuration>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483647" />
</requestFiltering>
</security>
</system.webServer>
【讨论】:
如果你想削弱这个网络服务器【参考方案8】:-
将 json 值保存为文件
上传 json 文件(同时获得唯一的文件名)
使用传递的文件名而不是 json 值调用 WCF 方法
从传递给方法的文件中读取数据
【讨论】:
以上是关于关于将大字符串发布到 Web 服务的建议的主要内容,如果未能解决你的问题,请参考以下文章