public void UpdateStatusString(FileRecvStatus status) { switch (status) { case FileRecvStatus.TOCONF: statusFile = "Da Confermare"; break; case FileRecvStatus.YSEND: statusFile = "Confermato"; break; case FileRecvStatus.NSEND: statusFile = "Annullato"; break; case FileRecvStatus.RECIVED: statusFile = "Ricevuto"; break; case FileRecvStatus.INPROGRESS: statusFile = "Download in corso..."; break; case FileRecvStatus.UNZIP: statusFile = "Fase unzip..."; break; case FileRecvStatus.RESENT: statusFile = "In attesa di rinvio"; break; } }
/// <summary> /// Check the status of a received file is the same of the one passed as argument /// </summary> /// <param name="ipUser">Remote user's ip</param> /// <param name="pathFile">Path file to update</param> /// <param name="status">File Status</param> /// <returns>Return true if the file was update, false otherwise</returns> public bool CheckRecvFileStatus(string ipUser, string pathFile, FileRecvStatus status) { lock (FileToRecive) { if (FileToRecive.ContainsKey(ipUser) && FileToRecive[ipUser].ContainsKey(pathFile) && (FileToRecive[ipUser][pathFile] == status)) { return(true); } return(false); } }
/// <summary> /// Update the status of the announced file /// </summary> /// <param name="ipUser">Remote user's ip</param> /// <param name="pathFile">Path file to receive</param> /// <param name="status">File Status</param> /// <returns>True if the file status was update, false otherwise</returns> public bool UpdateStatusRecvFileForUser(string ipUser, string pathFile, FileRecvStatus status) { lock (FileToRecive) { Dictionary <string, FileRecvStatus> currentDictionary; FileToRecive.TryGetValue(ipUser, out currentDictionary); if (currentDictionary.ContainsKey(pathFile)) { FileToRecive.AddOrUpdate(ipUser, (key) => currentDictionary, (key, oldValue) => { oldValue[pathFile] = status; return(oldValue); }); return(true); } return(false); } }
/// <summary> /// Add or update a received file /// </summary> /// <param name="ipUser">Remote user's ip</param> /// <param name="pathFile">Path file to update</param> /// <param name="status">File Status</param> public void AddOrUpdateRecvStatus(string ipUser, string pathFile, FileRecvStatus status) { lock (FileToRecive) { Dictionary <string, FileRecvStatus> currentDictionary; if (!FileToRecive.TryGetValue(ipUser, out currentDictionary)) { currentDictionary = new Dictionary <string, FileRecvStatus>(); } currentDictionary.Add(pathFile, status); FileToRecive.AddOrUpdate(ipUser, (key) => currentDictionary, (key, oldValue) => { if (oldValue.ContainsKey(pathFile)) { oldValue[pathFile] = status; return(oldValue); } else { return(oldValue.Concat(currentDictionary).ToDictionary(x => x.Key, x => x.Value)); } }); } }
/// <summary> /// Manage the download of a file sended by a remote host /// </summary> /// <param name="client">TCPClient object</param> /// <param name="stream">NetworkStream of the client</param> /// <param name="ip">Remote Ip user</param> /// <param name="fileOriginal">File Name</param> /// <param name="dim">File lenght(bytes)</param> async Task ServeReceiveFile(TcpClient client, NetworkStream stream, string ip, string fileOriginal, long dim) { string filename = ""; FileStream file; // Wait the asyncronous operation to chec if the same file exists in the filesystem await semaphoreForFile.WaitAsync(); filename = Utility.PathTmp() + "\\" + fileOriginal; if (File.Exists(filename)) { string[] splits = filename.Split('.'); string[] files = Directory.GetFiles(Utility.PathTmp(), Utility.PathToFileName(splits[splits.Length - 2]) + "*" + splits[splits.Length - 1]); splits[splits.Length - 2] += files.Count() > 0 ? ("_" + files.Count()) : ""; filename = string.Join(".", splits); _referenceData.UpdateFileName(fileOriginal, Utility.PathToFileName(filename), ip, FileRecvStatus.YSEND); } file = File.Create(filename); Console.WriteLine($"{DateTime.Now.ToString()}\t - ServeReceive created file on path {filename}"); semaphoreForFile.Release(); // Start file dowload // --------------------------------------------------------------- byte[] bytes = new byte[bufferSize * 64]; bool first = true; bool noFlag = false; // dimFile = total file dimension // dataReceived = total bytes that aren't received yet long dataReceived = dim; int i = 0; uint estimatedTimePacketCount = 0; double numerator = 0.0; double estimateTime = 0.0; DateTime started = DateTime.Now; TimeSpan estimatedTime = TimeSpan.FromSeconds(0); try { while (((i = stream.Read(bytes, 0, bytes.Length)) != 0) && dataReceived >= 0) { double dataReceivedJet = 0.0f; if (first) { noFlag = _referenceData.CheckAndUpdateRecvFileStatus(ip, fileOriginal); if (!noFlag) { await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.INPROGRESS, null, null); })); } first = false; } else { noFlag = _referenceData.CheckRecvFileStatus(ip, fileOriginal, FileRecvStatus.NSEND); } if (noFlag) { throw new Exception("File is rejected by remote host"); } if (dataReceived > 0 && dataReceived < i) { file.Write(bytes, 0, Convert.ToInt32(dataReceived)); dataReceivedJet = 100f; } else { file.Write(bytes, 0, i); dataReceivedJet = Math.Ceiling((double)(dim - dataReceived) / ((double)dim) * 100); } dataReceived -= i; if (estimatedTimePacketCount < 5) { numerator += (double)(dim - dataReceived); estimatedTimePacketCount++; } else { TimeSpan elapsedTime = DateTime.Now - started; estimateTime = elapsedTime.TotalSeconds * dataReceived / numerator; estimatedTime = TimeSpan.FromSeconds(estimateTime); numerator = 0.0; estimatedTimePacketCount = 0; } string estimatedTimeJet = string.Format("{00:00}", estimatedTime.Minutes) + ":" + string.Format("{00:00}", estimatedTime.Seconds) + ":" + string.Format("{00:00}", estimatedTime.Milliseconds); await MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.INPROGRESS, estimatedTimeJet, dataReceivedJet); })); } file.Close(); // End file download, start unzip! // --------------------------------------------------------------- string fileNameToProcess = filename; string ipUser = ip; // Create a new task to execute the unzip asynchronously await Task.Run(() => { FileRecvStatus?currentStatusFile = _referenceData.GetStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess)); if (currentStatusFile == null) { return; } if (currentStatusFile.Value == FileRecvStatus.NSEND) { try { File.Delete(fileNameToProcess); } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - ExtractFileToSavePath Exception - {e.GetType()} {e.Message}"); obj.Release(); } } else { try { string savePathLocalUser = _referenceData.GetInfoLocalUser().SavePath; // Create directory if (fileNameToProcess.Contains("Dir")) { string nameFile = Utility.PathToFileName(fileNameToProcess); nameFile = fileNameToProcess.Replace("_" + ipUser.Replace(".", "_"), String.Empty); // Get directory name string[] parts = nameFile.Split('_'); nameFile = nameFile.Replace(parts[0] + "_", string.Empty); string nameDir = nameFile.Replace("_" + parts[parts.Length - 1], string.Empty); string destPath = Path.Combine(savePathLocalUser, nameDir); semaphoreForFile.Wait(); if (!Directory.Exists(destPath)) { Directory.CreateDirectory(destPath); } else { int numb = Directory.GetDirectories(savePathLocalUser, nameDir + "*").Count(); Directory.CreateDirectory(destPath + "_(" + numb + ")"); destPath += "_(" + numb + ")"; } // Unzip files ZipFile.ExtractToDirectory(fileNameToProcess, destPath); _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), FileRecvStatus.RECIVED); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.RECIVED, "-", 100); MainWindow.main.StopNotify(); })); semaphoreForFile.Release(); } else if (fileNameToProcess.Contains("Files")) { // In case of a zip full of files using (ZipArchive archive = ZipFile.OpenRead(fileNameToProcess)) { // Check of each file if it already exists a file with the same name semaphoreForFile.Wait(); foreach (ZipArchiveEntry entry in archive.Entries) { string nameFileToExtract = ""; if (File.Exists(Path.Combine(savePathLocalUser, entry.Name))) { string[] parts = entry.Name.Split('.'); string extension = parts[parts.Length - 1]; parts = parts.Take(parts.Count() - 1).ToArray(); string name = String.Join(".", parts); int numb = Directory.GetFiles(savePathLocalUser, name + "*" + extension).Length; nameFileToExtract = name + "_(" + numb + ")." + extension; } else { nameFileToExtract = entry.Name; } entry.ExtractToFile(Path.Combine(savePathLocalUser, nameFileToExtract)); } _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), FileRecvStatus.RECIVED); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, FileRecvStatus.RECIVED, "-", 100); MainWindow.main.StopNotify(); })); semaphoreForFile.Release(); } } } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - Exception on unzip file received - {e.GetType()} {e.Message}"); File.Delete(fileNameToProcess); FileRecvStatus status = FileRecvStatus.NSEND; _referenceData.UpdateStatusRecvFileForUser(ipUser, Utility.PathToFileName(fileNameToProcess), status); MainWindow.main.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { MainWindow.main.AddOrUpdateListFile(ip, fileOriginal, status, "-", 0); })); if (semaphoreForFile.CurrentCount < 1) { semaphoreForFile.Release(); } } finally { obj.Release(); } } }); await obj.WaitAsync(); } catch (Exception e) { Console.WriteLine($"{DateTime.Now.ToString()}\t - ServeReceiveFile Exception - {e.GetType()} {e.Message}"); file.Close(); File.Delete(filename); } }
/// <summary> /// Update the name of a received file /// </summary> /// <param name="OriginalFileName">original filename</param> /// <param name="fileName">update filename</param> /// <param name="ip">Remote user's ip</param> /// <param name="status">Status of the file</param> public void UpdateFileName(string originalFileName, string fileName, string ip, FileRecvStatus status) { lock (FileToRecive) { Dictionary <string, FileRecvStatus> currentDictionary; if (FileToRecive.TryGetValue(ip, out currentDictionary)) { if (currentDictionary.ContainsKey(originalFileName) && currentDictionary[originalFileName] == status) { currentDictionary.Remove(originalFileName); currentDictionary.Add(fileName, status); FileToRecive.AddOrUpdate(ip, (key) => currentDictionary, (key, oldValue) => { oldValue = currentDictionary; return(oldValue); }); } } } }