问题:WCF如何传输大文件
方案:主要有几种绑定方式netTcpbinding,basicHttpBinding,wsHttpbinding,设置相关的传输max消息选项,服务端和客户端都要设置,transferMode可以buffer,stream.
实例:netTcpbinding
直接代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.IO; using System.Runtime.Serialization; namespace FileWcfService { [ServiceContract(Name="KuoFileUpload",Namespace="http://www.xinvu.com/")] public interface IFileUpload { [OperationContract] void Upload(byte[] file); //[OperationContract] //此用于流模式 //void UploadStream(FileMessage fileMessage); } //[MessageContract] //public class FileMessage //{ // [MessageHeader] // public string FileName; // [MessageBodyMember] // public Stream FileData; //} }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.IO; using System.IO.Compression; namespace FileWcfService { [ServiceBehavior(Name = "MyFileUpload")] public class FileUpload : IFileUpload { public void Upload(byte[] file) { try { Console.WriteLine(file.Length); MemoryStream ms = new MemoryStream(file); GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress); MemoryStream msTemp = new MemoryStream(); gzip.CopyTo(msTemp); string path= @"E:abc"+DateTime.Now.Ticks.ToString()+".rar"; //简单重命名 Console.WriteLine(path); File.WriteAllBytes(path, msTemp.ToArray()); } catch (Exception ex) { Console.WriteLine(ex.Message); } } //public void UploadStream(FileMessage fileMessage) //{ // string path = @"e:" + fileMessage.FileName + DateTime.Now.Ticks.ToString() + ".rar"; // //简单重命名 // try // { // FileStream fs = new FileStream(path, FileMode.CreateNew); // fileMessage.FileData.CopyTo(fs); // fs.Flush(); // fs.Close(); // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // } //} } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace FileWcfService { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(FileUpload))) { if (host.State != CommunicationState.Opened) host.Open(); Console.WriteLine("服务已启动……"); Console.WriteLine(); Console.Read(); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.IO; using System.IO.Compression; namespace WebApplication1 { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void Button1_Click(object sender, EventArgs e) { DateTime date = DateTime.Now; FileUpload.KuoFileUploadClient file = new FileUpload.KuoFileUploadClient(); byte[] buffer = this.FileUpload1.FileBytes; MemoryStream ms = new MemoryStream(); GZipStream zip = new GZipStream(ms, CompressionMode.Compress); zip.Write(buffer, 0, buffer.Length); byte[] buffer_zip = ms.ToArray(); zip.Close(); ms.Close(); //If the file bigger than 100MB, usually, there will be fault: //Failed to allocate a managed memory buffer of 208073270 bytes. The amount of available memory may be low. //I don't know how to salve this solution.So, please use stream mode. file.Upload(buffer_zip); zip.Close(); Response.Write(date.ToString() + "---" + DateTime.Now.ToString() + "<br/> Before:" + buffer.Length + ":After" + buffer_zip.ToString() + "<br/>"); Response.Write(FileUpload1.FileName); } protected void Button2_Click(object sender, EventArgs e) { //DateTime date = DateTime.Now; //FileUpload.KuoFileUploadClient file = new FileUpload.KuoFileUploadClient(); //FileUpload.FileMessage filedata = new FileUpload.FileMessage(); //using (MemoryStream ms = new MemoryStream()) //{ // filedata.FileName = this.FileUpload1.FileName; // filedata.FileData = this.FileUpload1.PostedFile.InputStream; // file.UploadStream(filedata); // Response.Write(date.ToString() + "---" + DateTime.Now.ToString() + "<br/>"); // Response.Write(FileUpload1.FileName); //} } } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <!--
流模式启用netTcpBindConfig,buffer启用netTcpBindingBuffer,人懒
--> <!--<netTcpBinding> <binding name="netTcpBindConfig" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Streamed" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647 " maxBufferSize="2147483647 " maxConnections="10" maxReceivedMessageSize="2147483647 " > <readerQuotas maxDepth="32" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="Transport"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> </security> </binding> </netTcpBinding>--> <netTcpBinding> <binding name="netTcpBindingBuffer" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647 " maxBufferSize="2147483647 " maxConnections="10" maxReceivedMessageSize="2147483647 " > <readerQuotas maxDepth="32" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="Transport"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> </security> </binding> </netTcpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="MyFileUpload"> <serviceMetadata /> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> <services> <service name="FileWcfService.FileUpload" behaviorConfiguration="MyFileUpload"> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:8089/FileService"/> </baseAddresses> </host> <!--<endpoint address="" binding="netTcpBinding" contract="FileWcfService.IFileUpload" bindingConfiguration="netTcpBindConfig" ></endpoint>--> <endpoint address="" binding="netTcpBinding" contract="FileWcfService.IFileUpload" bindingConfiguration="netTcpBindingBuffer" ></endpoint> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" ></endpoint> </service> </services> </system.serviceModel> </configuration>
实例二:basicHttpBinding ,实验上传1.5G没问题,局域网
新建一个web站点,加入一个wcf data service.

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using System.IO; namespace WcfService1 { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 [ServiceContract] public interface IGetDataService { [OperationContract] void UploadFile(FileData file); } [MessageContract] public class FileData { [MessageHeader] public string filename; [MessageBodyMember] public Stream data; } }

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using System.IO; namespace WcfService1 { public class GetDataService : IGetDataService { public void UploadFile(FileData file) { FileStream fs = new FileStream("D:\" + file.filename, FileMode.OpenOrCreate); try { BinaryReader reader = new BinaryReader(file.data); byte[] buffer; BinaryWriter writer = new BinaryWriter(fs); long offset = fs.Length; writer.Seek((int)offset, SeekOrigin.Begin); do { buffer = reader.ReadBytes(1024); writer.Write(buffer); } while (buffer.Length > 0); fs.Close(); file.data.Close(); } catch (Exception e) { throw new Exception(e.Message); } finally { fs.Close(); file.data.Close(); } } } }

protected void Button1_Click(object sender, EventArgs e) { FileData file = new FileData(); file.filename = FileUpload1.FileName; file.data = FileUpload1.PostedFile.InputStream; GetDataService c = new GetDataService(); c.UploadFile(file); Response.Write("文件传输成功!"); }

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> <httpRuntime maxRequestLength="2147483647" /> </system.web> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IGetDataService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="01:10:00" sendTimeout="01:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Streamed" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:52884/mex" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGetDataService" contract="IGetDataService" name="BasicHttpBinding_IGetDataService" /> </client> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /></system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true" /> </system.webServer> </configuration>