开启流模式,主要是设置一个叫TransferMode的属性,所以,你看看哪些Binding的派生类有这个属性就可以了。
TransferMode其实是一个举枚,看看它的几个有效值:
- Buffered:缓冲模式,说白了就是在内存中缓冲,一次调用就把整个消息读/写完,也就是我们最常用的方式,就是普通的操作协定的调用方式;
- StreamedRequest:只是在请求的时候使用流,说简单一点就是在传入方法的参数使用流,如 int MyMethod(System.IO.Stream stream);
- StreamedResponse:就是操作协定方法返回一个流,如 Stream MyMethod(string file_name);
一般而言,如果使用流作为传入参数,最好不要使用多个参数。
1、服务端
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.IO;
namespace Server
{
class Program
{
//设置服务并启动
static void Main()
{
//服务基地址
Uri baseUri = new Uri("http://localhost:3000/Service");
//声明服务器主机
using (ServiceHost 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");
//添加服务描述
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
//启动服务
try
{
host.Open();
Console.WriteLine("服务已启动");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
//关闭服务
host.Close();
}
}
}
/// <summary>
/// 定义服务协定
/// </summary>
[ServiceContract]
public interface IService
{
[OperationContract]
ResponseMessage UpLoadFile(StreamFile stream);
}
/// <summary>
/// 实现服务协定
/// </summary>
public class MyService : IService
{
public ResponseMessage UpLoadFile(StreamFile stream)
{
ResponseMessage result=new ResponseMessage();
if (stream == null || stream.FileStream == null || string.IsNullOrEmpty(stream.FileName))
{
result.IsSuccessed = false;
result.ErrorMessage = "流文件为空!";
return result;
}
try
{
using (FileStream fs = new FileStream(stream.FileName, FileMode.OpenOrCreate, FileAccess.Write))
{
// 我们不用对两个流对象进行读写,只要复制流就OK
stream.FileStream.CopyTo(fs);
fs.Flush();
result.IsSuccessed = true;
Console.WriteLine("{0}接收到客户端发送的流,已保存到{1}", DateTime.Now.ToLongTimeString(), stream.FileName);
}
}
catch (Exception ex)
{
result.ErrorMessage = ex.Message;
result.IsSuccessed = false;
}
return result;
}
}
[MessageContract]
public class StreamFile
{
/// <summary>
/// 流文件名称
/// </summary>
[MessageHeader]
public string FileName { get; set; }
/// <summary>
/// 流文件
/// </summary>
[MessageBodyMember]
public Stream FileStream { get; set; }
}
[MessageContract]
public class ResponseMessage
{
/// <summary>
/// 是否成功
/// </summary>
[MessageBodyMember]
public bool IsSuccessed { get; set; }
/// <summary>
/// 错误信息
/// </summary>
[MessageBodyMember]
public string ErrorMessage { get; set; }
}
}
2、客户端
using System;
using System.Windows.Forms;
using System.IO;
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnOpen_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "所有文件|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
txtFileName.Text = ofd.FileName;
}
}
private async void btnUpLoad_Click(object sender, EventArgs e)
{
if (txtFileName.Text.Trim() == "")
{
MessageBox.Show("请选择上传的文件!");
btnOpen.Focus();
return;
}
btnUpLoad.Enabled = false;
FileStream fs = new FileStream(txtFileName.Text.Trim(), FileMode.Open, FileAccess.Read);
WS.ServiceClient sc = new WS.ServiceClient();
WS.StreamFile sf = new WS.StreamFile(Path.GetFileName(txtFileName.Text.Trim()), fs);
var response = await sc.UpLoadFileAsync(sf);
if (response.IsSuccessed)
{
MessageBox.Show("上传成功");
}
else
{
MessageBox.Show(string.Format("上传失败!错误信息:{0}", response.ErrorMessage));
}
btnUpLoad.Enabled = true;
}
}
}