介紹
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