/// <summary> /// 从文本信息里面解析出任务信息 /// </summary> /// <param name="taskMessage"></param> /// <returns></returns> public static FileTaskInfo DecompileTaskInfo(Host Host, Message msg) { if (!msg.IsFileAttached || string.IsNullOrEmpty(msg.ExtendMessage)) return null; FileTaskInfo task = new FileTaskInfo(FileTransferDirection.Receive, msg.PackageNo, Host); string[] f = msg.ExtendMessage.Split('\a'); for (int i = 0; i < f.Length; i++) { string[] ef = f[i].Split(':'); if (ef.Length < 5) continue; int index = 0; string name = ""; ulong size = 0ul; ulong filetypeAttr; if (!int.TryParse(ef[0], out index) || !ulong.TryParse(ef[2], System.Globalization.NumberStyles.AllowHexSpecifier, null, out size) || !ulong.TryParse(ef[4], System.Globalization.NumberStyles.AllowHexSpecifier, null, out filetypeAttr)) continue; name = ef[1]; if (string.IsNullOrEmpty(name)) continue; else name = Network.TCPThread.replaceReg.Replace(name, "_"); task.TaskList.Add(new FileTaskItem() { TaskInfo = task, TotalSize = size, CancelPadding = false, FileCount = 0, FolderCount = 0, FinishedFileCount = 0, FinishedSize = 0, FinishedFolderCount = 0, EndTime = null, FullPath = "", CurrentFileTransfered = 0, Index = index, IsFolder = (filetypeAttr & (ulong)Define.Consts.Cmd_FileType_Option.Dir) == (ulong)Define.Consts.Cmd_FileType_Option.Dir, StartTime = null, CurrentName = name, CurrentFileSize = (filetypeAttr & (ulong)Define.Consts.Cmd_FileType_Option.Dir) == (ulong)Define.Consts.Cmd_FileType_Option.Dir ? 0ul : size, State = FileTaskItemState.Scheduled, Name = name }); } if (task.TaskList.Count == 0) return null; else return task; }
/// <summary> /// 创建一个新的 SendTaskExpires 对象. /// </summary> public SendTaskRelease(FileTaskInfo task) { Task = task; InitializeComponent(); }
/// <summary> /// 添加文件传输任务 /// </summary> /// <param name="task">任务信息</param> public void AddReceiveTask(FileTaskInfo task) { if (task == null) throw new ArgumentNullException(); if (task.RemoteHost == null || task.TaskList == null || task.TaskList.Count == 0 || task.PackageID == 0) throw new ArgumentException(); //进行必要的初始化 task.Direction = FileTransferDirection.Receive; task.TaskList.ForEach(s => s.TaskInfo = task); //设置集合关系 if (this.ReceiveTask.Contains(task)) return; this.ReceiveTask.Add(task); this.OnReceiveTaskAdded(new FileTaskEventArgs(task)); StartReceive(); }
/// <summary> /// 添加文件传输任务 /// </summary> /// <param name="task">任务信息</param> public void AddSendTask(FileTaskInfo task) { if (task == null) throw new ArgumentNullException(); if (task.RemoteHost == null || task.TaskList == null || task.TaskList.Count == 0 || task.PackageID == 0) throw new ArgumentException(); if (SendTask.ContainsKey(task.PackageID)) return; //进行必要的初始化 task.Direction = FileTransferDirection.Send; task.TaskList.ForEach(s => s.TaskInfo = task); //设置集合关系 SendTask.Add(task.PackageID, task); OnSendTaskAdded(new FileTaskEventArgs(task)); }
/// <summary> /// 接收文件 /// </summary> /// <param name="client"></param> /// <param name="task"></param> /// <param name="item"></param> void PerformFileReceive_File(TcpClient client, FileTaskInfo task, FileTaskItem item) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Initializing); //创建文件 System.IO.FileInfo fileinfo = new FileInfo(item.FullPath); if (fileinfo.Exists) item.CurrentFileTransfered = (ulong)fileinfo.Length; if (item.CurrentFileSize <= item.CurrentFileTransfered) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); return; } //创建文件 System.IO.FileStream writer = null; try { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(item.FullPath)); writer = fileinfo.OpenWrite(); } catch (Exception) { OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.CreateFile, item.FullPath, task.RemoteHost)); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } //创建网络流 NetworkStream netStream = null; try { netStream = client.GetStream(); } catch (Exception) { OnNetworkError(new EventArgs()); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } using (writer) { using (netStream) { //发送文件请求 PackedNetworkMessage pnm = MessagePacker.BuildNetworkMessage(Message.Create(task.RemoteHost, task.RemoteHost.HostSub.Ipv4Address, Config.GetRandomTick(), Config.HostName, Config.HostUserName, Consts.Commands.GetFileData, 0ul, string.Format("{0:x}:{1:x}:{2}", task.PackageID, item.Index, item.CurrentFileTransfered), "")); if (!SendDataInBuffer(netStream, pnm.Data, pnm.Data.Length)) return; //发送请求 TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; byte[] buffer = new byte[SendBuffer]; int length = buffer.Length; while (item.State != FileTaskItemState.Canceling && client.Connected && (length = ReceiveByBuffer(netStream, buffer, length)) > 0) { if (!WriteBufferToFile(task.RemoteHost, writer, item.FullPath, buffer, length)) return; item.CurrentFileTransfered += (ulong)length; item.FinishedSize += (ulong)length; //判断还有多少 length = buffer.Length; ulong restLength = item.CurrentFileSize - item.CurrentFileTransfered; if (restLength < (ulong)length) length = (int)restLength; } } } //判断是否完成 if (item.State == FileTaskItemState.Canceling) TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Canceled); else if (item.CurrentFileTransfered == item.CurrentFileSize) TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); else TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); }
//传输文件 bool ProcessFileTransfer(TcpClient client, NetworkStream netStream, FileTaskInfo task, FileTaskItem item, string currentDirectory, string fileName, ulong fileSize, bool updateTotal) { FileStream writer = null; string path = Path.Combine(currentDirectory, fileName); try { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path)); writer = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); } catch (Exception) { OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.CreateFile, path, task.RemoteHost)); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return false; } //初始化传输参数 item.CurrentFileSize = fileSize; item.CurrentFileTransfered = 0ul; item.CurrentName = fileName; if (updateTotal) { item.TotalSize += fileSize; } item.FileCount++; using (writer) { byte[] buffer = new byte[SendBuffer]; int length = 0; int readlength = buffer.Length; if ((ulong)readlength > item.CurrentFileSize) readlength = (int)item.CurrentFileSize; while (item.State != FileTaskItemState.Canceling && client.Connected && item.CurrentFileTransfered < item.CurrentFileSize && (length = ReceiveByBuffer(netStream, buffer, readlength)) > 0) { if (!WriteBufferToFile(task.RemoteHost, writer, path, buffer, length)) break; item.CurrentFileTransfered += (ulong)length; item.FinishedSize += (ulong)length; readlength = buffer.Length; if ((ulong)readlength > item.CurrentFileSize - item.CurrentFileTransfered) readlength = (int)(item.CurrentFileSize - item.CurrentFileTransfered); } writer.Close(); System.Diagnostics.Debug.Assert(item.CurrentFileTransfered <= item.CurrentFileSize, string.Format("传输文件异常。{0} 预计长度:{1} ,实际写入 {2}", item.CurrentName, item.CurrentFileSize, item.CurrentFileTransfered)); if (item.CurrentFileTransfered < item.CurrentFileSize) { if (item.State != FileTaskItemState.Canceling) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); } return false; } else { item.FinishedFileCount++; return true; } } }
/// <summary> /// 从文本信息里面解析出任务信息 /// </summary> /// <param name="taskMessage"></param> /// <returns></returns> public static FileTaskInfo DecompileTaskInfo(Host Host, Message msg) { if (!msg.IsFileAttached || string.IsNullOrEmpty(msg.ExtendMessage)) { return(null); } FileTaskInfo task = new FileTaskInfo(FileTransferDirection.Receive, msg.PackageNo, Host); string[] f = msg.ExtendMessage.Split('\a'); for (int i = 0; i < f.Length; i++) { string[] ef = f[i].Split(':'); if (ef.Length < 5) { continue; } int index = 0; string name = ""; ulong size = 0ul; ulong filetypeAttr; if (!int.TryParse(ef[0], out index) || !ulong.TryParse(ef[2], System.Globalization.NumberStyles.AllowHexSpecifier, null, out size) || !ulong.TryParse(ef[4], System.Globalization.NumberStyles.AllowHexSpecifier, null, out filetypeAttr)) { continue; } name = ef[1]; if (string.IsNullOrEmpty(name)) { continue; } else { name = Network.TCPThread.replaceReg.Replace(name, "_"); } task.TaskList.Add(new FileTaskItem() { TaskInfo = task, TotalSize = size, CancelPadding = false, FileCount = 0, FolderCount = 0, FinishedFileCount = 0, FinishedSize = 0, FinishedFolderCount = 0, EndTime = null, FullPath = "", CurrentFileTransfered = 0, Index = index, IsFolder = (filetypeAttr & (ulong)Define.Consts.Cmd_FileType_Option.Dir) == (ulong)Define.Consts.Cmd_FileType_Option.Dir, StartTime = null, CurrentName = name, CurrentFileSize = (filetypeAttr & (ulong)Define.Consts.Cmd_FileType_Option.Dir) == (ulong)Define.Consts.Cmd_FileType_Option.Dir ? 0ul : size, State = FileTaskItemState.Scheduled, Name = name }); } if (task.TaskList.Count == 0) { return(null); } else { return(task); } }
/// <summary> /// 处理文件请求 /// </summary> /// <param name="host"></param> /// <param name="task"></param> private void AddReceiveTask(Host host, FileTaskInfo task) { OpenChatTab(host, true, s => { s.ReceiveFileRequired(task); if (Env.ClientConfig.ChatConfig.AutoChangeCurrentTabToNew) { this.SelectTab(s as TabPage); } }); //SOUND if (!Forms.FrameContainer.ContainerForm.IsMute && Env.ClientConfig.Sound.EnableNewFileSound) Env.SoundManager.PlayNewFile(); }
/// <summary> /// 发送单个文件 /// </summary> /// <param name="client"></param> /// <param name="task"></param> /// <param name="item"></param> void PerformSendFile(TcpClient client, FileTaskInfo task, FileTaskItem item) { System.IO.FileStream fs = null; System.Net.Sockets.NetworkStream writer = null; try { writer = client.GetStream(); } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return; } try { fs = new System.IO.FileStream(item.FullPath, System.IO.FileMode.Open, System.IO.FileAccess.Read); } catch (Exception) { if (writer != null) writer.Close(); TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, item.FullPath, task.RemoteHost)); return; } using (fs) { //检测断点数据是否正确 if (item.CurrentFileTransfered < 0 || item.CurrentFileTransfered > (ulong)fs.Length) item.CurrentFileTransfered = 0; fs.Seek((long)item.CurrentFileTransfered, System.IO.SeekOrigin.Begin); //设置当前任务信息 item.CurrentFileSize = (ulong)fs.Length; TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; using (writer) { byte[] buffer = new byte[SendBuffer]; //缓冲区 while (item.CurrentFileTransfered < item.CurrentFileSize) { int bytesRead = fs.Read(buffer, 0, buffer.Length); try { writer.Write(buffer, 0, bytesRead); } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); break; } //更新进度 item.CurrentFileTransfered += (ulong)bytesRead; item.FinishedSize += (ulong)bytesRead; } item.FinishedFileCount++; writer.Close(); } fs.Close(); //标记任务完成 if (item.State != FileTaskItemState.Failure) TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Finished); } }
//发送要求创建文件命令 bool PerformSendDirectory_SendCreateDirCommand(string path, NetworkStream stream, FileTaskInfo task, FileTaskItem item) { string strCMD = string.Format(":{0}:{1}:{2:x}:", string.IsNullOrEmpty(path) ? "." : System.IO.Path.GetFileName(path), 0, (int)(string.IsNullOrEmpty(path) ? Consts.Cmd_FileType_Option.RetParent : Consts.Cmd_FileType_Option.Dir)); byte[] bytes = null; if (task.RemoteHost.IsEnhancedContractEnabled) bytes = System.Text.Encoding.Unicode.GetBytes(strCMD); else bytes = System.Text.Encoding.Default.GetBytes(strCMD); if (!string.IsNullOrEmpty(path)) item.FinishedFolderCount++; try { stream.Write(System.Text.Encoding.Default.GetBytes((bytes.Length + 4).ToString("x4")), 0, 4); stream.Write(bytes, 0, bytes.Length); return true; } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return false; } }
//发送文件夹中的文件 bool PerformSendDirectory_SendFilesInDirectory(string path, NetworkStream stream, FileTaskInfo task, FileTaskItem item, bool updateTotal) { System.IO.FileInfo fileinfo = new System.IO.FileInfo(path); if (!fileinfo.Exists) { OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, path, task.RemoteHost)); } if (updateTotal) item.TotalSize += (ulong)fileinfo.Length; item.CurrentName = fileinfo.Name; item.CurrentFileTransfered = 0; item.CurrentFileSize = (ulong)fileinfo.Length; string strCMD = string.Format(":{0}:{1:x}:{2:x}:", fileinfo.Name, fileinfo.Length, (int)Consts.Cmd_FileType_Option.Regular); byte[] bytes = null; if (task.RemoteHost.IsEnhancedContractEnabled) bytes = System.Text.Encoding.Unicode.GetBytes(strCMD); else bytes = System.Text.Encoding.Default.GetBytes(strCMD); try { stream.Write(System.Text.Encoding.Default.GetBytes((bytes.Length + 4).ToString("x4")), 0, 4); stream.Write(bytes, 0, bytes.Length); } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return false; } //写入文件数据 FileStream reader = null; try { reader = fileinfo.OpenRead(); } catch (Exception) { OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.OpenFileToSend, path, task.RemoteHost)); TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return false; } using (reader) { byte[] buffer = new byte[SendBuffer]; while (item.CurrentFileTransfered < (ulong)reader.Length) { int bytesRead = reader.Read(buffer, 0, buffer.Length); item.CurrentFileTransfered += (ulong)bytesRead; item.FinishedSize += (ulong)bytesRead; try { stream.Write(buffer, 0, bytesRead); } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return false; } } reader.Close(); } item.FinishedFileCount++; return true; }
//发送文件夹 void PerformSendDirectory(TcpClient client, FileTaskInfo task, FileTaskItem item) { NetworkStream stream = null; try { stream = client.GetStream(); } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); return; } string currentDirectory = item.FullPath; //当前处理路径 Stack<string> directoryStack = new Stack<string>(); //文件夹栈 directoryStack.Push(""); bool needUpdateTotal = item.TotalSize == 0; //是否需要在发送的时候更新统计 TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; using (stream) { while (!string.IsNullOrEmpty(currentDirectory) || directoryStack.Count > 0) { if (!PerformSendDirectory_SendCreateDirCommand(currentDirectory, stream, task, item)) return; if (string.IsNullOrEmpty(currentDirectory)) { if (directoryStack.Count > 0) currentDirectory = directoryStack.Pop(); //当前是空目录,则向上递归 continue; } //扫描目录和文件 string[] files = null, directories = null; try { files = System.IO.Directory.GetFiles(currentDirectory); directories = System.IO.Directory.GetDirectories(currentDirectory); item.FolderCount += directories.Length; item.FileCount += files.Length; } catch (Exception) { TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Failure); OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.QueryDirectory, item.FullPath, task.RemoteHost)); return; } //优先发送文件 foreach (var f in files) { if (!PerformSendDirectory_SendFilesInDirectory(f, stream, task, item, needUpdateTotal)) return; } //扫描子目录 if (directories.Length > 0) { directoryStack.Push(""); Array.ForEach(directories, s => { directoryStack.Push(s); }); currentDirectory = directoryStack.Pop(); //取出一个文件夹来发送 } else { //如果没有子目录,则置空当前目录,以命令流程向上返回 currentDirectory = null; } } if (item.State != FileTaskItemState.Failure) TaskManager.MarkSendTaskItemState(item, FileTaskItemState.Finished); } }
/// <summary> /// 向用户发送文件 /// </summary> /// <param name="taskItem">文件列表</param> /// <param name="textMessage">附加的文本信息</param> /// <param name="isRtf">附加的文本信息是RTF格式</param> /// <param name="isHtml">附加的文本信息是HTML格式</param> /// <param name="remoteHost">远程主机</param> public void PerformSendFile(FileTaskItem[] taskItem, string textMessage, bool isRtf, bool isHtml, Host remoteHost) { FileTaskInfo task = new FileTaskInfo(FileTransferDirection.Send, 0ul, remoteHost); task.TaskList.AddRange(taskItem); task.PackageID = Commander.SendTextMessage(remoteHost, textMessage, isHtml, isRtf, false, false, false, false, taskItem.BuildTaskMessage()); if (task.PackageID > 0) FileTaskManager.AddSendTask(task); }
/// <summary> /// 创建 FileTaskEventArgs class 的新实例 /// </summary> public FileTaskEventArgs(FileTaskInfo taskInfo) { TaskInfo = taskInfo; IsHandled = false; }
/// <summary> /// 创建 FileTaskEventArgs class 的新实例 /// </summary> public FileTaskEventArgs(FileTaskInfo taskInfo, FileTaskItem taskItem) { TaskInfo = taskInfo; TaskItem = taskItem; IsHandled = false; }
/// <summary> /// 创建一个新的 FileReceiveEventArgs 对象. /// </summary> public FileReceiveRequiredEventArgs(FileTaskInfo task, FileTaskItem item) { Task = task; Item = item; IsHandled = false; }
public void ReceiveFileRequired(FileTaskInfo task) { if (task == null) return; if (!browser.IsReady()) { notReadyScriptList.Add(task); return; } if (PaddingReceiveTask == null) PaddingReceiveTask = new List<FileTaskInfo>(); if (PaddingReceiveTask.FindIndex(s => s.PackageID == task.PackageID) == -1) PaddingReceiveTask.Add(task); //FIX:重试接收重复包编号错误 browser.InvokeScript("receiveFileRequired", task.ToJsonInfo(), Env.ClientConfig.FunctionConfig.Share_UseSameLocationToSave); }
/// <summary> /// 开始接收文件任务 /// </summary> /// <param name="task">任务信息</param> /// <param name="item">任务项目</param> internal void PerformFileReceive(FileTaskInfo task, FileTaskItem item) { #if DEBUG System.Console.WriteLine("开始接受文件,尝试连接到 " + task.RemoteHost.HostSub.Ipv4Address.ToString()); #endif using (TcpClient client = new TcpClient()) { client.ReceiveTimeout = this.Config.ConnectionTimeout; client.SendTimeout = this.Config.ConnectionTimeout; try { client.Connect(task.RemoteHost.HostSub.Ipv4Address); } catch (Exception) { this.TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); if (client.Connected) client.Close(); return; } //检测是文件夹还是单个文件 if (item.IsFolder) { PerformFileReceive_Folder(client, task, item); } else { PerformFileReceive_File(client, task, item); } client.Close(); } }
/// <summary> /// 接收文件夹 /// </summary> /// <param name="client"></param> /// <param name="task"></param> /// <param name="item"></param> void PerformFileReceive_Folder(TcpClient client, FileTaskInfo task, FileTaskItem item) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Initializing); //创建网络流 NetworkStream netStream = null; try { netStream = client.GetStream(); } catch (Exception) { OnNetworkError(new EventArgs()); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } bool updateTotal = item.TotalSize == 0; //是否在更新进度的时候需要更新总数 using (netStream) { //发送文件请求 PackedNetworkMessage pnm = MessagePacker.BuildNetworkMessage(Message.Create(task.RemoteHost, task.RemoteHost.HostSub.Ipv4Address, Config.GetRandomTick(), Config.HostName, Config.HostUserName, Consts.Commands.GetDirFiles, 0ul, string.Format("{0:x}:{1:x}:0:", task.PackageID, item.Index), "")); if (!SendDataInBuffer(netStream, pnm.Data, pnm.Data.Length)) return; //发送请求 TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; string filename; ulong size; bool isFolder, isRet; Stack<string> pathStack = new Stack<string>(); string currentPath = item.FullPath; while (client.Connected && item.State != FileTaskItemState.Canceling && ReadCmdHeader(netStream, task.RemoteHost, out filename, out size, out isFolder, out isRet)) { if (isRet) { if (pathStack.Count > 0) { currentPath = pathStack.Pop(); if (pathStack.Count == 0) break; //Fixed: 当当前队列不再有信息时,其实接收已经完成了。因为当前队列中最后一个肯定是文件夹自己。 } else break; } else if (isFolder) { //建立文件夹 if (!ProcessDirCmd(item, ref currentPath, pathStack, filename, updateTotal)) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } } else { //传文件 if (!ProcessFileTransfer(client, netStream, task, item, currentPath, filename, size, updateTotal)) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } } } netStream.Close(); } if (item.State == FileTaskItemState.Canceling) TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Canceled); else if (item.State != FileTaskItemState.Failure) TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); }
/// <summary> /// 创建一个新的 SendTaskExpires 对象. /// </summary> public SendTaskExpires(FileTaskInfo task) { Task = task; InitializeComponent(); }