Exemplo n.º 1
0
        private async Task DownloadFileAsync(Uri fullUrl, string filename)
        {
            string finalFilePath = Path.Combine(_config.SavingDirectory, filename);
            string tmpFilePath   = Path.Combine(_config.TemporaryDirectory, filename);

            // skip if exists
            if (File.Exists(finalFilePath))
            {
                return;
            }
            _logger.LogInformation($"Downloading ({fullUrl.AbsoluteUri})");
            bool     isSuccess        = false;
            int      numberOfAttempts = 0;
            TimeSpan timeCost         = TimeSpan.FromTicks(0);

            // BUG: If those fileinfo initialized here, it will be more likely to trigger IO error below
            // FileInfo tmpFileToWrite = new FileInfo(tmpFilePath);
            // FileInfo finalFileToWrite = new FileInfo(finalFilePath);
            while (true)
            {
                // BUG/WORKAROUND: If those fileinfo initialized here, it will seldom trigger IO error below
                FileInfo tmpFileToWrite   = new FileInfo(tmpFilePath);
                FileInfo finalFileToWrite = new FileInfo(finalFilePath);
                // busy waiting
                while (tmpFileToWrite.Exists && tmpFileToWrite.IsFileLocked())
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
                if (isSuccess)
                {
                    while (finalFileToWrite.Exists && finalFileToWrite.IsFileLocked())
                    {
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }
                    // finalFileToWrite.Delete();
                    // File.Move(tmpFilePath, finalFilePath);
                    tmpFileToWrite.MoveTo(finalFilePath, true);
                    _logger.LogInformation($"Time cost: {timeCost.TotalSeconds}s. ({fullUrl.AbsoluteUri})");
                    break;
                }
                if (numberOfAttempts >= _config.NumberOfAttemptsPreLink)
                {
                    // File.Delete(tmpFilePath);
                    tmpFileToWrite.Delete();
                    _logger.LogError($"Run out of attempts. ({fullUrl.AbsoluteUri})");
                    break;
                }
                try
                {
                    // File.Delete(tmpFilePath);
                    tmpFileToWrite.Delete();
                    using (var client = new WebDownload((int)TimeSpan.FromSeconds(_config.SecondsBeforeTimeout).TotalMilliseconds))
                    {
                        var stopwatch = new Stopwatch();
                        // using (var timer = new Timer())
                        // {
                        // timer.Interval = TimeSpan.FromSeconds(_config.SecondsBeforeTimeout).TotalMilliseconds;
                        // timer.Start();
                        var downloadTask = client.DownloadFileTaskAsync(fullUrl, tmpFilePath);
                        // bool isTimeout = false;
                        // timer.Elapsed += (sender, e) => this.Timeout(sender, e, downloadTask, out isTimeout);
                        // client.DownloadFile(fullUrl, filePath);
                        stopwatch.Start();
                        downloadTask.Wait(TimeSpan.FromSeconds(_config.SecondsBeforeTimeout));
                        stopwatch.Stop();
                        timeCost = stopwatch.Elapsed;
                        // timer.Stop();
                        // timeCostInSeconds = _config.SecondsBeforeTimeout - TimeSpan.FromMilliseconds(timer.Interval).TotalSeconds;
                        // isSuccess = !isTimeout;
                        isSuccess = downloadTask.IsCompleted;
                        // }
                    }
                }
                catch (IOException)
                {
                    throw;
                }
                // // BUG: not catching
                // catch (WebException)
                // {
                //     // System.Net.WebException : The operation has timed out.
                //     isSuccess = false;
                // }
                catch (Exception)
                {
                    isSuccess = false;
                }
                if (!isSuccess)
                {
                    _logger.LogError($"Timeout! ({fullUrl.AbsoluteUri})");
                }
                numberOfAttempts++;
            }
        }