最近这个项目要做一个Winfrom上传Execl到服务器。
就想到之前用Fleck做的一个小功能,但是客户端Web端的。百度吧,看有没有办法,开始找到fw4 ,但是要引用它的dll,是可以,继续找了会结果找到ClientWebSocket,只需要using System.Net.WebSockets;就好了,想着去试试。
网上很多Fleck的例子,server.Start 中只需要加上 socket.OnBinary = file =>{......},具体后面有图。
下面是客户端的:
ClientWebSocket ws = new ClientWebSocket();
//创建WebSocket
static string IP = ConfigurationManager.AppSettings["IP"];
static string Point = ConfigurationManager.AppSettings["Point"];
string url = "ws://"+ IP + ":"+ Point;
连接ws:
async void ClientWebSocketConnect()
{
try
{
if (ws.State != WebSocketState.Open)
{
ws = new ClientWebSocket();
await ws.ConnectAsync(new Uri(url), CancellationToken.None);
ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[100]);
WebSocketReceiveResult result = await
ws.ReceiveAsync(bytesReceived, CancellationToken.None);
var str = Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count);
label1.ForeColor = System.Drawing.Color.Green;
label1.Text = str;
}
else
{
await ws.ConnectAsync(new Uri(url), CancellationToken.None);
}
}
catch(Exception ex)
{
label1.Text = ex.Message;
}
}
/// <summary>
/// 关闭断开
/// </summary>
async void ClientWebSocketClose()
{
if (ws.State == WebSocketState.Open || ws.State == WebSocketState.CloseReceived)
{
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "用户关闭", CancellationToken.None);
ws.Dispose();
}
}
另外给Form1_FormClosing事件加了关闭连接,不然线程一直在,每次重启服务端就重新连接了。
用OpenFileDialog选择一个execl,上传
/// <summary>
/// 上传文件
/// </summary>
async void UpFile()
{
if (ws.State == WebSocketState.Open)
{
// 用文件流打开用户要发送的文件;
using (FileStream fs = new FileStream(txtSelectFile.Text, FileMode.Open))
{
//获取文件的名称和扩展名
string fileName = System.IO.Path.GetFileName(txtSelectFile.Text);
//文件的名称转byte[] 利用了web上面url编码的功能,带了编码,避免二进制过来汉字乱码
byte[] arrfileName = System.Web.HttpUtility.UrlEncodeToBytes(fileName, Encoding.GetEncoding("GB2312"));//string
//分隔符
byte[] arr_fgf = System.Text.Encoding.UTF8.GetBytes("|");
//定义数组 赋值计算总长度
byte[] arrFile = new byte[fs.Length + arrfileName.Length + arr_fgf.Length];
//组装字符串的方式
//把arrfileName复制到arrFile
Array.Copy(arrfileName, arrFile, arrfileName.Length);
//把arr_fgf复制到arrFile,在arrfileName之后
Array.Copy(arr_fgf, 0, arrFile, arrfileName.Length, arr_fgf.Length);
//把文件流写入arrFile指定位置
fs.Read(arrFile, (arrfileName.Length + arr_fgf.Length), (arrFile.Length - arrfileName.Length - arr_fgf.Length)); // 将文件中的数据读到arrFile数组中;
//以二进制方式发送WebSocket
var buffer = new ArraySegment<byte>(arrFile);
await ws.SendAsync(buffer, WebSocketMessageType.Binary, true, CancellationToken.None);
//清理控件
txtSelectFile.Clear();
//while (true)
//{
ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[100]);
//接收数据
WebSocketReceiveResult result = await ws.ReceiveAsync(bytesReceived, CancellationToken.None);
//byte[]转string
var str = Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count);
//if (str.Length > 0)
//{
if(str.Contains("上传成功"))
label1.ForeColor = System.Drawing.Color.Green;
else
label1.ForeColor = System.Drawing.Color.Red;
label1.Text = str;
// return;
//}
//}
}
}
}
这句是核心,选用二进制的方式
因为数据库要保存文件名称,以及文件路径,方便查找,就顺带把名字传过去了,是以 名称|文件 的方式来发送的。
文件的名称转byte[] 利用了web上面url编码的功能,带了编码,避免二进制过来汉字乱码,这个坑坑了大半天,逼得无奈用Web上的方法来处理了。测试的话就没得必要写这么麻烦。。。
服务端:
接收客户端传过来的byte[],直接写入文件,返回消息。
关键点都很简单,过程有点乱。。。然后把这个改成服务。。嗯嗯,差不多了。。。