private static void EncodeSendFileRequestExtend(BinaryWriter wtr, object extendObj) { UdpPacketSendFileRequestExtend extend = extendObj as UdpPacketSendFileRequestExtend; if (extend == null) { throw new Exception("[EncodeImageExtend]未想定附加包"); } using (MemoryStream ms = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(ms)) { LanFile file = extend.File; bw.Write(file.Name); bw.Write(file.Length); bw.Write(file.IsFolder); bw.Close(); ms.Close(); byte[] buf = ms.ToArray(); byte[] enBuf = SecurityFactory.Encrypt(buf, extend.EncryptKey); wtr.Write(enBuf.Length); wtr.Write(enBuf); } } }
private static UdpPacketSendFileRequestExtend ResolveSendFileRequestExtend(BinaryReader rdr, byte[] priKey) { int len = rdr.ReadInt32(); byte[] buf = rdr.ReadBytes(len); byte[] deBuf = SecurityFactory.Decrypt(buf, priKey); using (MemoryStream ms = new MemoryStream(deBuf)) { using (BinaryReader bw = new BinaryReader(ms)) { LanFile file = new LanFile(); file.Name = bw.ReadString(); file.Length = bw.ReadInt32(); file.IsFolder = bw.ReadBoolean(); bw.Close(); ms.Close(); UdpPacketSendFileRequestExtend extend = new UdpPacketSendFileRequestExtend(); extend.File = file; return(extend); } } }
private void _user_FileTransportProgressChanged(object sender, FileTransportEventArgs args) { TransportFile file = args.File; OutputLog("接收文件[" + file.File.Name + "]," + file.Progress + "%," + LanFile.HumanReadbleLen(file.TransportedLength) + "/" + LanFile.HumanReadbleLen(file.File.Length) + "," + LanFile.HumanReadbleLen(file.TransportedSpeed) + "/s"); }
protected override void OnItemClicked(ItemClickedEventArgs args) { if (args.Button == MouseButtons.Left) { MessageListItem item = args.Item as MessageListItem; Message m = item.Message; Rectangle rect = item.Bounds; foreach (DrawingObject dobj in item.DrawingObjects) { RectangleF drawingObjRect = dobj.Offset(rect.X, rect.Y); switch (dobj.Type) { //头像 case DrawingObjectType.ProfilePhoto: if (drawingObjRect.Contains(args.Location)) { UserProfileControl control = new UserProfileControl(); control.User = item.User; control.Show(this.PointToScreen(args.Location)); return; } break; case DrawingObjectType.Image: case DrawingObjectType.File: { if (drawingObjRect.Contains(args.Location)) { //点击了图像,显示大图, 或者打开文件 string path; if (m.Type == MessageType.Image) { path = (m as ImageMessage).OriginPath; } else { path = (m as FileMessage).OriginFilePath; } if (LanFile.Exists(path)) { Process.Start(path); } } break; } } } } else if (args.Button == MouseButtons.Right) { //交给显示右键菜单 } }
private long SendImageCore(LanUser user, Image image, string imagePath) { string path; if (image != null) { path = LanConfig.Instance.GetTempFileName(".png"); image.Save(path, ImageFormat.Png); } else { path = imagePath; } long len = LanFile.GetFileLength(path); if (len > UdpClientEx.UDP_MAX_BUF_SIZE) { //图像文件过大的话用文件形式发送 return(SendFile(user, path, true)); } else { UdpPacket packet = new UdpPacket(); packet.Address = user.IP; packet.Port = user.Port; packet.ToMAC = user.MAC; packet.Command = UdpPacket.CMD_SEND_IMAGE | UdpPacket.CMD_OPTION_NEED_RESPONSE; packet.FromMAC = this.MAC; UdpPacketImageExtend extend = new UdpPacketImageExtend(); extend.EncryptKey = user.SecurityKeys.Public; extend.Image = image ?? Image.FromFile(path); packet.Extend = extend; _client.Send(packet); if (image != null) { //直接发送图像的话,临时图片就删除 LanFile.Delete(path); } return(packet.ID); } }
public static void SetPhoto(string key, Image img) { string fileName = Path.Combine(LanConfig.Instance.ProfilePhotoPath, key); _cache.Remove(key); LanFile.Delete(fileName); if (img == null) { return; } using (Bitmap bmp = new Bitmap(img.Width, img.Height)) { bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution); using (Graphics g = Graphics.FromImage(bmp)) { g.DrawImageUnscaled(img, 0, 0); } bmp.Save(fileName, ImageFormat.Jpeg); } }
private void SendFile_Click(object sender, EventArgs e) { if (!this.SendMessageEnabled) { return; } using (OpenFileDialog ofd = new OpenFileDialog()) { ofd.Filter = "所有文件|*.*"; if (ofd.ShowDialog(this) == DialogResult.OK) { string fileName = ofd.FileName; long id = User.SendFile(Contacter, fileName); //保存发送记录 Store.Models.FileMessage m = new Store.Models.FileMessage(); m.FromUserId = this.User.ID; m.ToUserId = this.Contacter.ID; m.OriginFilePath = fileName; m.FileName = Path.GetFileName(fileName); m.FileLength = LanFile.GetFileLength(fileName); m.Flag = true; //默认成功,后面按照失败结果设定为false MessageListItem item = new MessageListItem(); item.ID = id; item.Message = m; item.User = this.User; item.State = MessageState.Sending; item.Save(); AddMessageItem(item, true); OnSendMessage(m); } } }
private void SendFileHandler(object clientobj) { LoggerFactory.Debug("begin send file"); TcpClient client = null; NetworkStream ns = null; try { client = clientobj as TcpClient; ns = client.GetStream(); if (!ns.CanRead) { //想定外 ns.Close(); client.Close(); OnError(Errors.NotExistTransportId, "未收到传送ID", null, null); return; } } catch (Exception e) { OnError(Errors.NetworkError, "尝试收取传送ID失败", null, e); return; } LoggerFactory.Debug("get file id"); //取得传送的文件ID byte[] buff = null; int len = 0; try { buff = new byte[this.ReceiveBufferSize]; len = ns.Read(buff, 0, buff.Length); } catch (Exception e) { ns.Close(); client.Close(); OnError(Errors.NetworkError, "尝试收取传送ID失败", null, e); return; } TcpPacket packet = null; try { IPacketResolver resolver = PacketResolverFactory.CreateResolver(buff, 0, len, this.SecurityKeys.Private); packet = resolver.Resolve() as TcpPacket; } catch (Exception e) { ns.Close(); client.Close(); OnError(Errors.ResolveError, "解密文件ID失败", null, e); return; } LoggerFactory.Debug("get file"); TcpPacketRequestFileTransportExtend extend = packet.Extend as TcpPacketRequestFileTransportExtend; if (!_transportFileDic.TryRemove(extend.FileID, out TransportFile file)) { ns.Close(); client.Close(); OnError(Errors.NotExistTransportId, "不存在的文件ID=" + extend.FileID, null, null); return; } LanFile lanFile = file.File; if (!File.Exists(lanFile.Path)) { ns.Close(); client.Close(); OnError(Errors.FileOpenError, "不存在的文件:" + lanFile.Path, file, null); return; } LoggerFactory.Debug("open file"); FileStream fs = null; try { fs = new FileStream(lanFile.Path, FileMode.Open, FileAccess.Read); //TODO 对于大文件用MemoryMappedFile提高速度,但是对这个类用法不是很清楚,效率也未做实验,暂时不对应 //MemoryMappedFile f1s = MemoryMappedFile.CreateFromFile(fs, FileMode.Open, "", 1024, MemoryMappedFileAccess.Read); //f1s.CreateViewStream } catch (Exception e) { ns.Close(); client.Close(); OnError(Errors.FileOpenError, "文件打开失败", file, e); return; } LoggerFactory.Debug("sending file"); try { //发送文件 file.StartTransport(); long lastProgressTicks = file.NowTransportTicks; while ((len = fs.Read(buff, 0, buff.Length)) != 0) { ns.Write(buff, 0, len); file.Transported(len); if (file.TransportedLength == file.File.Length || (DateTime.Now.Ticks - lastProgressTicks) > this._progressChangeInterval) //避免进度太频繁,500ms一次 { OnProgressChanged(file); lastProgressTicks = file.NowTransportTicks; } } } catch (Exception e) { OnError(Errors.NetworkError, "文件传输网络错误", file, e); } finally { fs.Close(); ns.Flush(); ns.Close(); client.Close(); OnCompleted(file); } LoggerFactory.Debug("end send file"); }
public void Receive(TransportFile file) { TaskFactory taskFactory = new TaskFactory(); taskFactory.StartNew(() => { LoggerFactory.Debug("start receive file:id={0}", file.ID); string tmpPath = file.SavePath + "." + Path.GetRandomFileName().Replace(".", "") + ".lamim"; FileStream fs = null; try { fs = new FileStream(tmpPath, FileMode.Create); } catch (Exception e) { OnError(Errors.FileOpenError, "打开文件失败:" + tmpPath, file, e); return; } LoggerFactory.Debug("opened file:" + tmpPath); LoggerFactory.Debug("try connect remote:remote={0}, port={1}", file.Remote, file.Port); TcpClient tcpClient = null; NetworkStream ns = null; try { tcpClient = new TcpClient(AddressFamily.InterNetwork) { ReceiveBufferSize = this.ReceiveBufferSize }; tcpClient.Connect(file.Remote, file.Port); ns = tcpClient.GetStream(); } catch (Exception e) { OnError(Errors.NetworkError, "连接失败", file, e); return; } LoggerFactory.Debug("conneted remote:remote={0}, port={1}", file.Remote, file.Port); LoggerFactory.Debug("encode packet, request file:id={0}", file.ID); TcpPacket packet = null; EncodeResult result = null; try { //发送要接受的文件ID TcpPacketRequestFileTransportExtend extend = new TcpPacketRequestFileTransportExtend { EncryptKey = file.PublicKey, FileID = file.ID }; packet = new TcpPacket { Command = TcpPacket.CMD_REQUEST_FILE_TRANSPORT, Extend = extend }; IPacketEncoder encoder = PacketEncoderFactory.CreateEncoder(packet); result = encoder.Encode(null); } catch (Exception e) { OnError(Errors.EncodeError, "请求文件ID包加密失败。" + packet.ToString(), file, e); return; } LoggerFactory.Debug("send packet, request file:id={0}", file.ID); try { ns.Write(result.Fragments[0], 0, result.Fragments[0].Length); } catch (Exception e) { OnError(Errors.NetworkError, "请求文件ID包发送失败", file, e); return; } LoggerFactory.Debug("receive file start:id={0}", file.ID); try { int len = 0; file.StartTransport(); long lastProgressTicks = file.NowTransportTicks; byte[] buff = new byte[this.ReceiveBufferSize]; while ((len = ns.Read(buff, 0, buff.Length)) != 0) { fs.Write(buff, 0, len); file.Transported(len); if (file.TransportedLength == file.File.Length || (DateTime.Now.Ticks - lastProgressTicks) > this._progressChangeInterval) //避免进度太频繁,500ms一次 { OnProgressChanged(file); lastProgressTicks = file.NowTransportTicks; } } LoggerFactory.Debug("receive file end:id={0}", file.ID); } catch (Exception e) { OnError(Errors.NetworkError, "文件接收失败", file, e); } finally { LoggerFactory.Debug("close connect and save file:id={0}", file.ID); //关闭连接 ns.Close(); tcpClient.Close(); fs.Flush(true); fs.Close(); if (LanFile.Rename(tmpPath, file.SavePath)) { //发送接收完毕 OnCompleted(file); } else { OnError(Errors.FileWriteError, "文件写入失败", file, null); } } LoggerFactory.Debug("end receive file:id={0}", file.ID); }); }
protected override void OnDrawItem(UI.DrawItemEventArgs args) { MessageListItem item = args.Item as MessageListItem; Message m = item.Message; args.DrawBackground(); Graphics g = args.Graphics; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; Rectangle rect = item.Bounds; Rectangle drawingObjRect; Point pos = PointToClient(MousePosition); foreach (DrawingObject dobj in item.DrawingObjects) { drawingObjRect = dobj.Offset(rect.X, rect.Y); switch (dobj.Type) { //头像 case DrawingObjectType.ProfilePhoto: { g.DrawImage(ProfilePhotoPool.GetPhoto(item.User.ID), drawingObjRect); if (drawingObjRect.Contains(pos)) { g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height); } break; } //时间, 昵称,状态 case DrawingObjectType.Title: { string text = item.User.NickName + " " + m.Time.ToString("yyyy/MM/dd HH:mm:ss"); if (!m.Flag) { text += " 传送失败"; } TextRenderer.DrawText(g, text, args.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y) , m.Flag ? SUCCESS_TITLE_COLOR : ERROR_TITLE_COLOR, TextFormatFlags.Left); break; } //文本消息 case DrawingObjectType.TextBlock: { TextBlockObj tb = dobj.Tag as TextBlockObj; StringPart sp = tb.StringPart; int selStart = Math.Min(tb.SelectionStart, tb.SelectionEnd); int selEnd = Math.Max(tb.SelectionStart, tb.SelectionEnd); string str1 = selStart == -1 ? sp.String : sp.String.Substring(0, selStart); string str2 = selStart == -1 ? "" : sp.String.Substring(selStart, tb.SelectionLength); string str3 = selEnd == -1 ? "" : sp.String.Substring(selEnd + 1); //选择前的文本 if (!string.IsNullOrEmpty(str1)) { TextRenderer.DrawText(g, str1, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor, StringMeasurer.TextFormatFlags); } //选择中文本 if (!string.IsNullOrEmpty(str2)) { int w1 = StringMeasurer.Width(g, sp.Font, str1, sp.TextFormatFlags); int w2 = StringMeasurer.Width(g, sp.Font, str2, sp.TextFormatFlags); drawingObjRect.X += w1; drawingObjRect.Width = w2; g.FillRectangle(BrushPool.GetBrush(TEXT_SELECTION_BACK_COLOR), drawingObjRect); TextRenderer.DrawText(g, str2, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), TEXT_SELECTION_FORE_COLOR, StringMeasurer.TextFormatFlags); //选择后的文本 if (!string.IsNullOrEmpty(str3)) { drawingObjRect.X += w2; drawingObjRect.Width = dobj.Width - w1 - w2; TextRenderer.DrawText(g, str3, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor, StringMeasurer.TextFormatFlags); } } break; } case DrawingObjectType.Image: { Image image = (m as ImageMessage).Image; g.DrawImage(image, drawingObjRect); if (drawingObjRect.Contains(pos)) { g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height); } else { g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height); } break; } case DrawingObjectType.File: { FileMessage fm = m as FileMessage; //底背景 g.FillRectangle(Brushes.White, drawingObjRect); if (drawingObjRect.Contains(pos)) { g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height); } else { g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height); } //文件名,文件大小,ICON Image image = FileIconPool.GetIcon(fm.OriginFilePath); int imageWidth = 64; int imageHeight = 64 * image.Height / image.Width; Rectangle imageRect = new Rectangle(drawingObjRect.X + FILE_SEND_WIDTH - imageWidth - MARGIN, drawingObjRect.Y + MARGIN, imageWidth, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3); Rectangle fileNameRect = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + MARGIN, FILE_SEND_WIDTH - imageWidth - MARGIN * 3, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3); Rectangle fontRect = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + FILE_SEND_HEIGHT - Font.Height - MARGIN, FILE_SEND_WIDTH - MARGIN * 2, Font.Height); Rectangle pieRect = new Rectangle(drawingObjRect.X + (FILE_SEND_WIDTH - PROGRESS_PIE_D) / 2, drawingObjRect.Y + (FILE_SEND_HEIGHT - PROGRESS_PIE_D) / 2, PROGRESS_PIE_D, PROGRESS_PIE_D); Rectangle processRect = new Rectangle(drawingObjRect.X, drawingObjRect.Y + (FILE_SEND_HEIGHT - Font.Height * 2) / 2, FILE_SEND_WIDTH, Font.Height * 2); //当文件名超过显示部分时,中间用省略号表示 string str = fm.FileName; SizeF s = g.MeasureString(fm.FileName, Font, new System.Drawing.SizeF((float)fileNameRect.Width, (float)fileNameRect.Height), StringFormat.GenericDefault, out int count, out int lines); if (s.Height >= fileNameRect.Height & str.Length >= count) { //由于会出现半行的情况,直接写死了所取的字符串数目 str = str.Substring(0, 36) + "・・・" + str.Substring(str.Length - 4); } g.DrawImage(image, imageRect.X, imageRect.Y, imageWidth, imageHeight); g.DrawString(str, args.Font, Brushes.Black, fileNameRect); TextRenderer.DrawText(g, LanFile.HumanReadbleLen(fm.FileLength), args.Font, fontRect, Color.FromArgb(0, 0, 0), TextFormatFlags.Left); if (item.State == MessageState.Receiving || item.State == MessageState.Sending) { //接受进度 g.FillRectangle(MESSAGELIST_PROGRESS_BACKGROUND_BRUSH, drawingObjRect); g.DrawPie(PROGRESS_PEN, pieRect, 0, 360); g.FillPie(MESSAGELIST_PROGRESS_FILLED_BRUSH, pieRect, 0, 360 * item.Progress / 100); //TODO 显示剩余时间,传输速度 TextRenderer.DrawText(g, item.Progress + "%" + "\r\n" + LanFile.HumanReadbleLen(item.FileTransportedLength) + "/" + LanFile.HumanReadbleLen(fm.FileLength), args.Font, processRect, Color.FromArgb(0, 0, 0), TextFormatFlags.HorizontalCenter); } break; } } } }