最近这个项目要做一个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 = awaitws.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复制到arrFileArray.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数组中;//以二进制方式发送WebSocketvar 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[]转stringvar str = Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count);//if (str.Length > 0)//{if(str.Contains("上传成功"))label1.ForeColor = System.Drawing.Color.Green;elselabel1.ForeColor = System.Drawing.Color.Red;label1.Text = str;// return;//}//}}}}
这句是核心,选用二进制的方式
因为数据库要保存文件名称,以及文件路径,方便查找,就顺带把名字传过去了,是以 名称|文件 的方式来发送的。
文件的名称转byte[] 利用了web上面url编码的功能,带了编码,避免二进制过来汉字乱码,这个坑坑了大半天,逼得无奈用Web上的方法来处理了。测试的话就没得必要写这么麻烦。。。
服务端:
接收客户端传过来的byte[],直接写入文件,返回消息。
关键点都很简单,过程有点乱。。。然后把这个改成服务。。嗯嗯,差不多了。。。