Example #1
0
        /// <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);
            }
        }