WCF流与文件传输

来源:互联网 发布:电脑office软件下载 编辑:程序博客网 时间:2024/06/07 10:05

开启流模式,主要是设置一个叫TransferMode的属性,所以,你看看哪些Binding的派生类有这个属性就可以了。
TransferMode其实是一个举枚,看看它的几个有效值:
Buffered:缓冲模式,说白了就是在内存中缓冲,一次调用就把整个消息读/写完,也就是我们最常用的方式,就是普通的操作协定的调用方式;
StreamedRequest:只是在请求的时候使用流,说简单一点就是在传入方法的参数使用流,如 int MyMethod(System.IO.Stream stream);
StreamedResponse:就是操作协定方法返回一个流,如 Stream MyMethod(string file_name);
一般而言,如果使用流作为传入参数,最好不要使用多个参数,如这样:
来源: http://blog.csdn.net/tcjiaan/article/details/8248543
1.新建两个WinForm, Server, Client
2.Server中添加引用System.ServiceModel
3.定义服务协定

[ServiceContract(Namespace = "MyNamespace")]
public interface IService
{
[OperationContract]
ResultMessage UpLoadFile(TransferFileMessage tMsg);
}
/// <summary>
/// 参数协定 消息协定作为传入参数,则只能有一个参数
/// </summary>
[MessageContract]
public class TransferFileMessage
{
[MessageHeader]
public string File_Name; //文件名
[MessageBodyMember]
public Stream File_Stream; //文件流
}
/// <summary>
/// 返回结果协定 双工模式下的返回结果要么是void 要么是消息协定
/// </summary>
[MessageContract]
public class ResultMessage
{
[MessageHeader]
public string ErrorMessage;
[MessageBodyMember]
public bool IsSuccessed;
}

4.在MyService中实现协定

class MyService : IService
{
public ResultMessage UpLoadFile(TransferFileMessage tMsg)
{
ResultMessage rMsg = new ResultMessage();
if (tMsg == null || tMsg.File_Stream == null)
{
rMsg.ErrorMessage = "传入的参数无效。";
rMsg.IsSuccessed = false;
return rMsg;
}
try
{
using (FileStream outputStream = new FileStream(tMsg.File_Name, FileMode.OpenOrCreate, FileAccess.Write))
{
// 我们不用对两个流对象进行读写,只要复制流就OK
tMsg.File_Stream.CopyTo(outputStream);
outputStream.Flush();
rMsg.IsSuccessed = true;
Console.WriteLine("在{0}接收到客户端发送的流,已保存到{1}。", DateTime.Now.ToLongTimeString(), tMsg.File_Name);
}
}
catch (Exception ex)
{
rMsg.IsSuccessed = false;
rMsg.ErrorMessage = ex.Message;
}
return rMsg;
}
}

5.在Server界面添加按钮和文本框
.这里写图片描述

在按钮中添加如下代码 注意启用流模式 设置接收消息最大范围 默认只有几十K 传文件不够用

   ServiceHost host;    private void startService_Click(object sender, EventArgs e)    {        Uri baseURI = new Uri("http://localhost:8008/Service");        host = new ServiceHost(typeof(MyService), baseURI);        // 添加绑定和终结点          BasicHttpBinding binding = new BasicHttpBinding();        // 启用流模式          binding.TransferMode = TransferMode.StreamedRequest;        binding.MaxBufferSize = 1024;        // 接收消息的最大范围为500M          binding.MaxReceivedMessageSize = 500 * 1024 * 1024;        host.AddServiceEndpoint(typeof(IService), binding, "/test");        // 为了能让VS生成客户端代码,即WSDL文档,故要添加以下行为          ServiceMetadataBehavior mdBehavior = new ServiceMetadataBehavior()        {            HttpGetEnabled = true        };        host.Description.Behaviors.Add(mdBehavior);        //如果服务顺利启动,则提示,处理Opened事件          host.Opened += (sender2, e2) => { textBox1.AppendText("服务已启动\r\n"); };        // 启动服务器          try        {            host.Open();        }        catch (Exception ex)        {            textBox1.AppendText(ex.Message);        }    }    private void closeService_Click(object sender, EventArgs e)    {        // 关闭服务器          host.Close();        textBox1.AppendText("服务已关闭\r\n");    }

6.以管理员身份启动Service
这里写图片描述
7.保持服务开启,在Client中添加服务引用
这里写图片描述
8.注意高级选项中的内容如下配置
这里写图片描述
9.在Client界面中添加按钮和标签
这里写图片描述
在按钮中添加代码

private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "MP3音频文件|*.mp3";
if (DialogResult.OK.Equals(dlg.ShowDialog()))
{
this.lbSelectedFilename.Text = dlg.FileName;
this.lbMessage.Text = "准备就绪";
}
}
private async void button2_Click(object sender, EventArgs e)
{
if (!File.Exists(this.lbSelectedFilename.Text))
{
return;
}
FileStream fs = new FileStream(this.lbSelectedFilename.Text, FileMode.Open, FileAccess.Read);
WS.ServiceClient cl = new WS.ServiceClient();
var response = await cl.UpLoadFileAsync(Path.GetFileName(this.lbSelectedFilename.Text), fs);
if (response.IsSuccessed == true)
this.lbMessage.Text = "上传完成。";
else
this.lbMessage.Text = "错误信息:" + response.ErrorMessage;
}

10.启动程序
这里写图片描述

参考自 http://blog.csdn.net/tcjiaan/article/details/8248543
推荐原作者的传说中的WCF系列