介紹
WCF(Windows Communication Foundation) - 消息處理:使用流數據傳輸文件,減少內存開銷。
示例
1、服務
IStreamed.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.IO; namespace WCF.ServiceLib.Message { /**//// <summary> /// 消息契約(定義與 SOAP 消息相對應的強類型類) /// </summary> [MessageContract] public class FileWrapper { /**//// <summary> /// 指定數據成員為 SOAP 消息頭 /// </summary> [MessageHeader] public string FilePath; /**//// <summary> /// 指定將成員序列化為 SOAP 正文中的元素 /// </summary> [MessageBodyMember] public Stream FileData; } /**//// <summary> /// IStreamed接口 /// </summary> [ServiceContract] public interface IStreamed { /**//// <summary> /// 上傳文件 /// </summary> /// <remarks> /// 1、支持數據流傳輸的綁定有:BasicHttpBinding、NetTcpBinding 和 NetNamedPipeBinding /// 2、流數據類型必須是可序列化的 Stream 或 MemoryStream // /3、傳遞時消息體(Message Body)中不能包含其他數據,即參數中只能有一個System.ServiceModel.MessageBodyMember /**//// </remarks> /// <param name="fileWrapper">WCF.ServiceLib.Message.FileWrapper</param> [OperationContract] void UploadFile(FileWrapper fileWrapper); } }
Streamed.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.IO; namespace WCF.ServiceLib.Message { /**//// <summary> /// IStreamed類 /// </summary> public class Streamed : IStreamed { /**//// <summary> /// 上傳文件 /// </summary> /// <param name="fileWrapper">WCF.ServiceLib.Message.FileWrapper</param> public void UploadFile(FileWrapper fileWrapper) { var sourceStream = fileWrapper.FileData; var targetStream = new FileStream(fileWrapper.FilePath, FileMode.Create, FileAccess.Write, FileShare.None); var buffer = new byte[4096]; var count = 0; while ((count = sourceStream.Read(buffer, 0, buffer.Length)) > 0) { targetStream.Write(buffer, 0, count); } targetStream.Close(); sourceStream.Close(); } } }
2、宿主
Streamed.cs
using (ServiceHost host = new ServiceHost(typeof(WCF.ServiceLib.Message.Streamed))) { host.Open(); Console.WriteLine("服務已啟動(WCF.ServiceLib.Message.Streamed)"); Console.WriteLine("按<ENTER>停止服務"); Console.ReadLine(); }
App.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <!--name - 提供服務的類名--> <!--behaviorConfiguration - 指定相關的行為配置--> <service name="WCF.ServiceLib.Message.Streamed" behaviorConfiguration="MessageBehavior"> <!--address - 服務地址--> <!--binding - 通信方式--> <!--contract - 服務契約--> <!--bindingConfiguration - 指定相關的綁定配置--> <endpoint address="Message/Streamed" binding="netTcpBinding" contract="WCF.ServiceLib.Message.IStreamed" bindingConfiguration="StreamedBindingConfiguration" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:12345/Message/Streamed/"/> <add baseAddress="net.tcp://localhost:54321/"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="MessageBehavior"> <!--httpGetEnabled - 使用get方式提供服務--> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <!--transferMode - 指示通道是使用流處理模式還是緩沖模式來傳輸請求和響應消息--> <!--maxReceivedMessageSize - 在采用此綁定配置的通道上可接收的最大消息大小(單位:字節)--> <!--receiveTimeout - 在傳輸引發異常之前可用於完成讀取操作的時間間隔--> <binding name="StreamedBindingConfiguration" transferMode="Streamed" maxReceivedMessageSize="1073741824" receiveTimeout="00:10:00" /> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
3、客戶端
Streamed.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.ServiceModel; using System.IO; namespace Client2.Message { /**//// <summary> /// 演示Message.Streamed的類 /// </summary> public class Streamed { /**//// <summary> /// 流數據上傳文件 /// </summary> /// <param name="source">源文件地址</param> /// <param name="destination">目標路徑</param> public void HelloStreamed(string source, string destination) { try { var proxy = new MessageSvc.Streamed.StreamedClient(); var sr = new System.IO.FileStream( source, System.IO.FileMode.Open); proxy.UploadFile(destination + Path.GetFileName(source), sr); sr.Close(); proxy.Close(); MessageBox.Show("上傳成功"); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } } }
App.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <!--address - 服務地址--> <!--binding - 通信方式--> <!--contract - 服務契約--> <endpoint address="net.tcp://localhost:54321/Message/Streamed" binding="netTcpBinding" contract="MessageSvc.Streamed.IStreamed" bindingConfiguration="StreamedBindingConfiguration" /> </client> <bindings> <netTcpBinding> <!--transferMode - 指示通道是使用流處理模式還是緩沖模式來傳輸請求和響應消息--> <!--sendTimeout - 在傳輸引發異常之前可用於完成寫入操作的時間間隔--> <binding name="StreamedBindingConfiguration" transferMode="Streamed" sendTimeout="00:10:00" /> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
運行結果:
上傳文件後提示上傳成功
OK