关于此,还有许多其他类似的问题.不幸的是,许多人似乎在某些方面相互欺骗.我希望这个会帮助别人并解决其他问题.
我的项目要求是通过IIS将250MB文件上传到IIS中托管的后端WCF服务.我为IIS中托管的后端WCF服务创建了一些单元测试.他们是:
1) Upload 1MB File
2) Upload 5MB File
3) Upload 10MB file
4) Upload 20MB File
5) Upload 200MB File
Run Code Online (Sandbox Code Playgroud)
马上就可以了,我们需要使用某种流式传输或分块文件传输. 我用过这个样本.
该示例描述了一种使用.NET Stream对象的方法.使用流对象的一个副作用是必须使用Message contract.将Stream放在函数的参数列表中是不够的.所以我们这样做.
默认情况下,此WCF服务的web.config非常精简.没有任何作用:
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
Run Code Online (Sandbox Code Playgroud)
经过大量的搜索和实验,很明显BasicHttpBinding与Stream对象和MessageContract的这种组合不兼容. 我们必须切换到WSHttpBinding.
为此,服务器的web.config在以下部分稍微复杂一些:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
</behavior>
<behavior name="FileServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" maxConcurrentInstances="500"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="FileServiceBinding" closeTimeout="10:01:00"
maxBufferPoolSize="104857600"
maxReceivedMessageSize="104857600" openTimeout="10:01:00"
receiveTimeout="10:10:00" sendTimeout="10:01:00"
messageEncoding="Mtom">
<readerQuotas maxDepth="104857600" maxStringContentLength="104857600"
maxArrayLength="104857600" maxBytesPerRead="104857600"
maxNameTableCharCount="104857600" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="FileServiceBehavior" name="OMS.Service.FileService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="FileServiceBinding" contract="OMS.Service.IFileService"></endpoint>
</service>
</services>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
没有任何工作可言,1MB文件现在通过没有问题.
为了传递大于4MB的文件,您必须调整IIS中的web.config中的设置(WCF服务的服务器端) Microsoft的这篇文章解释了该设置是什么. 例如,如果您将其设置为8192,那么您将能够上传5MB文件,但不能更大.
<httpRuntime maxRequestLength="8192" />
Run Code Online (Sandbox Code Playgroud)
我设置了一些淫秽的测试 - 2147483647. 前4个文件通过这个门.
由于下一个原因,200MB没有机会进入这个大门:
System.InsufficientMemoryException: Failed to allocate a managed memory buffer of 279620368 bytes. The amount of available memory may be low. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
Run Code Online (Sandbox Code Playgroud)
这张海报很好地描述了这个问题的解释.
想想这样.200MB的文件永远不会脱离客户端.它必须由客户端完全加载,加密然后传输到服务器.
当您使用Visual Studio 2010为服务生成代理类时,它会将一些内容放入您的app.config中.对我来说,它看起来像这样:
<binding
name="Binding_IFileService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" />
</security>
</binding>
Run Code Online (Sandbox Code Playgroud)
关键是安全模式. 它默认设置为"消息".该值由服务器上设置的任何值拾取.默认情况下,您的服务器使用消息级别安全性.
如果您尝试在服务器上强制它像这样:
<security mode="None">
Run Code Online (Sandbox Code Playgroud)
你收到这个错误:
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://localhost:8080/oms/FileService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
Run Code Online (Sandbox Code Playgroud)
(我记得更新客户端代理)
所以,这就是它代表我的地方......帮助!
好详细的问题:)
您的最后一条错误消息是 404 文件未找到。通常这是因为文件丢失或站点已关闭。检查这一点只是为了排除这种情况。
根据上次更改,您已关闭基于消息的加密。此更改需要在客户端和服务器上完成。如果一侧正在加密,而另一侧不希望消息被加密,那么就会感到困惑。