我想使用WCF
在客户端和服务器之间传输文件。我读过许多文章,其中有些人为此目的使用Stream
模式。但出于限制,我决定以缓冲模式创建服务。例如,考虑一下:
[OperationContract]
void UploadFile(Guid systemKey, string fileName, byte[] fileContent, string userName);
服务器Web配置:
...
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" maxRequestLength="2147483647" executionTimeout="7200"/>
</system.web>
....
<bindings>
<basicHttpBinding>
<binding name="myBasicBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
closeTimeout="01:50:00"
openTimeout="01:50:00"
sendTimeout="01:50:00"
receiveTimeout="01:50:00"
messageEncoding="Mtom">
<readerQuotas maxDepth="128" maxStringContentLength="8388608" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
....
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295"/>
</requestFiltering>
</security>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
和客户端配置:
<system.web>
<compilation debug="true" targetFramework="4.6"/>
<httpRuntime targetFramework="4.6" maxRequestLength="2147483647" executionTimeout="7200"/>
</system.web>
...
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295"/>
</requestFiltering>
</security>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicEndpoint"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
closeTimeout="01:50:00"
openTimeout="01:50:00"
sendTimeout="01:50:00"
receiveTimeout="01:50:00"
messageEncoding="Mtom">
<readerQuotas maxDepth="128" maxStringContentLength="8388608" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/fts.svc" binding="basicHttpBinding" bindingConfiguration="basicEndpoint" contract="ServiceReference1.Ifts" name="basicEndpoint"/>
</client>
</system.serviceModel>
我可以上传400MB
文件,但是当文件大小为500MB
或更高时,出现此错误:
System.InsufficientMemoryException HResult = 0x8013153D 消息=无法分配1073741824字节的托管内存缓冲区。可用内存量可能不足。 来源= mscorlib
内部异常1: OutOfMemoryException:引发了类型为System.OutOfMemoryException的异常。 \
我认为我为2GB
数据设置了值,但在500MB
上却失败了。
谢谢
此代码在本地运行,并且我有16GB
RAM。问题出在哪里,上传harge文件应该更改什么值?
谢谢
答案 0 :(得分:2)
我记得我正在处理大型文件传输,并且我使用buffered
模式进行传输,但不是最好的解决方案,因为一段时间后,我发现有关内存泄漏或某些相关内存的异常,因此我进行了更改到transferMode="Streamed"
,并且一切正常,通过buffered
模式,这意味着消息的全部内容在发送之前或接收之后都存在于内存中。虽然对于大多数情况而言,这是一个不错的策略,并且对于诸如数字签名和可靠传递之类的消息传递功能而言是必需的,但是大消息可能会耗尽系统的资源。
看看here。
为避免在WCF一直使用BufferManager重用缓冲区的过程中始终创建新缓冲区,直到maxBufferPoolSize
指定的限制,
buffers
的创建和销毁成本很高。您可以使用BufferManager类来管理缓冲池。
您可以尝试增加maxBufferPoolSize
来查看是否可以减少内存使用量。我强烈建议不要将其增加到最大值,因为我认为在应用程序域得到回收之前,池中的缓冲区永远不会释放。一段时间的高流量可能会导致大量内存被使用而从未释放。
因此,我建议您使用streamed
模式来传输大文件。
要拆分文件并使用大型流,请使用下面的链接可能会对您有所帮助:
Multiple file in one Stream, custom stream
Best way to return large file as split zip files,Stream or Byte array WCF
它也可能对您有帮助
Multiple stream in one stream will not passed to client properly
答案 1 :(得分:1)
OutOfMemoryException表示进程正在使用允许的最大内存。您是否在尝试上载此大文件时调试代码?您的IDE可能导致此问题。 而且,我认为,上载大文件时,最好的方法是将文件拆分为较小的缓冲区,然后在服务器端重新创建它们。 另一种方法是在服务器和客户端之间使用FTP来处理上传下载本身。