Pisces.IM.Client.WPF(持续更新...)

 Pisces.IM.Client.WPF

 服务端监听各个客户端的连接情况

WPF 客户端

                            基础聊天

 

文件收发

 

              历史记录

 

 

WPF 界面部分用到了MaterialDesignThemes(4.9.0)

emoji的支持:Emoji.Wpf(0.3.4)

 Helper

ImageHelper.cs 处理WPF中图像的使用

 1 internal static class ImageHelper
 2 {
 3     public static BitmapImage ToBitmapImage(this Bitmap bitmap)
 4     {
 5         var bitmapImage = new BitmapImage();
 6 
 7         using var ms = new MemoryStream();
 8         bitmap.Save(ms, ImageFormat.Png);
 9         bitmapImage.BeginInit();
10         bitmapImage.StreamSource = ms;
11         bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
12         bitmapImage.EndInit();
13         bitmapImage.Freeze();
14 
15         return bitmapImage;
16     }
17 
18     public static BitmapImage? ToBitmapImage(this string path)
19     {
20         if (!File.Exists(path)) return null;
21 
22         var bi = new BitmapImage();
23         bi.BeginInit();
24         bi.UriSource = new Uri(path, UriKind.RelativeOrAbsolute);
25         bi.EndInit();
26         return bi;
27     }
28 
29     public static Bitmap ToBitmap(this BitmapSource source)
30     {
31         var bmp = new Bitmap(source.PixelWidth, source.PixelHeight, PixelFormat.Format32bppArgb);
32         var bmpData = bmp.LockBits(new System.Drawing.Rectangle(Point.Empty, bmp.Size),
33             ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
34         source.CopyPixels(Int32Rect.Empty, bmpData.Scan0, bmpData.Height * bmpData.Stride, bmpData.Stride);
35         bmp.UnlockBits(bmpData);
36 
37         var temp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppArgb);
38         var g = Graphics.FromImage(temp);
39         g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height));
40         g.Dispose();
41         return temp;
42     }
43 
44 }
View Code

获取系统中默认文件的的icon

 1         private static ImageSource? GetFileIcon(string? fileName)
 2         {
 3 
 4             if (!File.Exists(fileName)) return null;
 5 
 6             if (string.IsNullOrEmpty(fileName)) return null;
 7 
 8             var icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName);
 9 
10             return icon?.ToBitmap().ToBitmapImage();
11 
12         }
View Code

如下图:

 

Views

ChatView.xaml.cs 

文件的收发

因为目前并未设计服务端进行消息和文件的缓存,所以文件的收发未采用FTP,目前选择Socket直接收发,目前文件限制到50M以内

同时将文件拆分各个小的数据包, 每个小数据包大小为2048byte,并包装成消息收发协议。

文件数据包的发送同样遵照Pisces.IM.Communication中对数据包处理。

发送文件之前,将告诉文件接收方,当文件接收方做好接收准备后并告知发送方可以发送文件数据了。

 1          var fileTransferInfo = new FileTransferInfo()
 2          {
 3              FileId = GenerateIdHelper.GenerateId().ToString(),
 4              FileExtension = FileHelper.GetFileExtension(file),
 5              FileHashCode = FileHelper.GetFileSHA256HexString(file),
 6              FileName = FileHelper.GetFileShortName(file),
 7              FileSize = FileHelper.GetFileSize(file),
 8              FromId = _globalDataContext.MySelfID,
 9              ToId = SelectedItem.Id,
10              ReceiverStatus = false,
11              SenderStatus = true,
12          };
FileTransferInfo

FileExtension :告知文件的类型

FileHashCode:告知文件的SHA256校验值,防止在传输过程中文件是否被修改或者损坏

FileSize:告知文件的大小

 

文件的拆分与发送

 1   private void SendFile(FileTransferInfo fileTransferInfo)
 2   {
 3 
 4       Task.Run(() =>
 5       {
 6           if (_globalDataContext == null) return;
 7           if (_globalDataContext.FileTransfer == null) return;
 8 
 9           var fileTransfer = _globalDataContext.FileTransfer;
10 
11           if (string.IsNullOrEmpty(fileTransferInfo.ToId)) return;
12           if (string.IsNullOrEmpty(fileTransferInfo.FromId)) return;
13           if (string.IsNullOrEmpty(fileTransferInfo.FileId)) return;
14           if (string.IsNullOrEmpty(fileTransferInfo.FileName)) return;
15           var content = _chatContentViewModel.ChatContents[fileTransferInfo.ToId];
16 
17           if (content == null) return;
18           var fileContent = content.Where(x => x.FileContent?.FileId == fileTransferInfo.FileId).FirstOrDefault();
19           if (fileContent == null) return;
20           if (fileContent.FileContent == null) return;
21           if (fileTransferInfo.FileSize <= 0) return;
22 
23           var sdl = 1024 * 2;
24           //Number of slices
25           var nos = fileTransferInfo.FileSize / sdl;
26           //Final sliced data
27           long fsd = fileTransferInfo.FileSize % sdl;
28 
29           using var steam = File.OpenRead(fileTransferInfo.FileName);
30 
31           if (nos > 0)
32           {
33               var count = 0;
34               while (count < nos)
35               {
36                   var sd = new byte[sdl];
37                   steam.Seek(sdl * count, SeekOrigin.Begin);
38                   steam.Read(sd, 0, sdl);
39                   var buffer = FilePacketService.Combined(fileTransferInfo.FromId,
40                       fileTransferInfo.ToId, 1, sd, fileTransferInfo.FileId);
41                   fileTransfer.GetCurrentSocket().Send(buffer);
42                   count++;
43                   fileContent.FileContent.CurrentFileSize += buffer.Length;
44                   fileContent.FileContent.SetProgressValue();
45                   Thread.Sleep(5);
46               }
47 
48               var sd_f = new byte[fsd];
49               steam.Seek(sdl * count, SeekOrigin.Begin);
50               steam.Read(sd_f, 0, sd_f.Length);
51               var buffer_f = FilePacketService.Combined(fileTransferInfo.FromId,
52                      fileTransferInfo.ToId, 1, sd_f, fileTransferInfo.FileId);
53   
54                  fileTransfer.GetCurrentSocket().Send(buffer_f);
55      
56                   fileContent.FileContent.CurrentFileSize += buffer_f.Length;
57                   fileContent.FileContent.SetProgressValue();
58              
59           }
60           else
61           {
62               var sd = new byte[fileTransferInfo.FileSize];
63               steam.Read(sd, 0, sd.Length);
64               var buffer = FilePacketService.Combined(fileTransferInfo.FromId,
65                                 fileTransferInfo.ToId, 1, sd, fileTransferInfo.FileId);
66 
67               fileTransfer.GetCurrentSocket().Send(buffer);
68 
69               fileContent.FileContent.CurrentFileSize += buffer.Length;
70               fileContent.FileContent.SetProgressValue();
71 
72 
73           }
74 
75           steam.Flush();
76           steam.Close();
77           fileContent.FileContent.ProcessbarVisibility = Visibility.Hidden;
78       });
79   }
View Code

 

 

 

完整源码:github

 

posted @ 2023-09-25 10:44  pisces91  阅读(80)  评论(1)    收藏  举报