/// <summary>
        /// Downloads a file from a specified Internet address.
        /// </summary>
        /// <param name="remotePath">Internet address of the file to download.</param>
        /// <param name="localPath">Local file name where to store the content of the download, if null a temporary file name will be generated.</param>
        /// <param name="timeOut">Duration in miliseconds before cancelling the  operation.</param>
        /// <param name="progress">Report the progress of the download</param>
        /// <param name="ct">Cancellation token</param>
        public static async Task <Tuple <string, string, Exception> > DownloadFileTaskAsync(string remotePath,
                                                                                            string localPath = null, int timeOut = int.MaxValue, IProgress <long> progress = null, CancellationTokenSource ct = null)
        {
            var watch = Stopwatch.StartNew();

            try
            {
                if (remotePath == null)
                {
                    Logger.Debug("DownloadFileTaskAsync (null remote path): skipping");
                    throw new ArgumentNullException(nameof(remotePath));
                }

                if (localPath == null)
                {
                    Logger.Debug(
                        $"DownloadFileTaskAsync (null local path): generating a temporary file name for {remotePath}");
                    localPath = Path.GetTempFileName();
                }

                if (File.Exists(localPath))
                {
                    var fileInfo = new FileInfo(localPath).Length;
                    if (fileInfo != 0)
                    {
                        return(new Tuple <string, string, Exception>(remotePath, localPath, null));
                    }
                }

                var direcory = Path.GetDirectoryName(localPath);
                if (!string.IsNullOrEmpty(direcory) && !Directory.Exists(direcory))
                {
                    Directory.CreateDirectory(direcory);
                }

                using (var client = new NoKeepAliveWebClient())
                {
                    if (progress != null)
                    {
                        client.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
                        {
                            progress.Report(e.BytesReceived / e.TotalBytesToReceive);
                        };
                    }

                    TimerCallback timerCallback = c =>
                    {
                        var webClient = (WebClient)c;
                        if (!webClient.IsBusy)
                        {
                            return;
                        }
                        webClient.CancelAsync();
                        Logger.Debug($"DownloadFileTaskAsync (time out due): {remotePath}");
                    };

                    try
                    {
                        using (new Timer(timerCallback, client, timeOut, Timeout.Infinite))
                        {
                            if (ct != null)
                            {
                                await client.DownloadFileTaskAsync(remotePath, localPath, ct.Token);
                            }
                            else
                            {
                                await client.DownloadFileTaskAsync(remotePath, localPath);
                            }
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        watch.Stop();
                        Logger.Debug(
                            "DownloadFileTaskAsync cancelled.");
                        return(new Tuple <string, string, Exception>(remotePath, null, exception));
                    }
                    catch (ObjectDisposedException exception)
                    {
                        watch.Stop();
                        Logger.Info(
                            $"DownloadFileTaskAsync (can't cancel download, it has finished previously): {remotePath}");
                        return(new Tuple <string, string, Exception>(remotePath, null, exception));
                    }
                    catch (WebException exception)
                    {
                        watch.Stop();
                        Logger.Error($"DownloadFileTaskAsync: {exception.Message}");
                        return(new Tuple <string, string, Exception>(remotePath, null, exception));
                    }
                }
            }
            catch (Exception ex)
            {
                watch.Stop();
                Logger.Error(
                    $"DownloadFileTaskAsync (download failed): {remotePath} Additional informations : {ex.Message}");
                return(new Tuple <string, string, Exception>(remotePath, null, ex));
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug($"DownloadFileTaskAsync (downloaded in {elapsedMs} ms): {remotePath}");
            }

            return(new Tuple <string, string, Exception>(remotePath, localPath, null));
        }
Example #2
0
        /// <summary>
        /// Downloads a file from a specified Internet address.
        /// </summary>
        /// <param name="remotePath">Internet address of the file to download.</param>
        /// <param name="localPath">Local file name where to store the content of the download, if null a temporary file name will be generated.</param>
        /// <param name="timeOut">Duration in miliseconds before cancelling the  operation.</param>
        /// <param name="progress">Report the progress of the download</param>
        /// <param name="ct">Cancellation token</param>
        public static async Task<Tuple<string, string, Exception>> DownloadFileTaskAsync(string remotePath,
            string localPath = null, int timeOut = 10000, IProgress<long> progress = null, CancellationTokenSource ct = null)
        {
            try
            {
                var watch = Stopwatch.StartNew();

                if (remotePath == null)
                {
                    Logger.Debug("DownloadFileTaskAsync (null remote path): skipping");
                    throw new ArgumentNullException(nameof(remotePath));
                }

                if (localPath == null)
                {
                    Logger.Debug(
                        $"DownloadFileTaskAsync (null local path): generating a temporary file name for {remotePath}");
                    localPath = Path.GetTempFileName();
                }

                if (File.Exists(localPath))
                {
                    var fileInfo = new FileInfo(localPath).Length;
                    if (fileInfo != 0)
                    {
                        return new Tuple<string, string, Exception>(remotePath, localPath, null);
                    }
                }

                var direcory = Path.GetDirectoryName(localPath);
                if (!string.IsNullOrEmpty(direcory) && !Directory.Exists(direcory))
                {
                    Directory.CreateDirectory(direcory);
                }

                using (var client = new NoKeepAliveWebClient())
                {
                    if (progress != null)
                    {
                        client.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
                        {
                            progress.Report(e.BytesReceived/e.TotalBytesToReceive);
                        };
                    }

                    TimerCallback timerCallback = c =>
                    {
                        var webClient = (WebClient) c;
                        if (!webClient.IsBusy) return;
                        webClient.CancelAsync();
                        Logger.Debug($"DownloadFileTaskAsync (time out due): {remotePath}");
                    };

                    try
                    {
                        using (ct?.Token.Register(() => client.CancelAsync()))
                        using (new Timer(timerCallback, client, timeOut, Timeout.Infinite))
                        {
                            await client.DownloadFileTaskAsync(remotePath, localPath);
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        //TODO:Manage the disposed client when cancel async
                    }

                    watch.Stop();
                    var elapsedMs = watch.ElapsedMilliseconds;

                    Logger.Debug($"DownloadFileTaskAsync (downloaded in {elapsedMs} ms): {remotePath}");
                    return new Tuple<string, string, Exception>(remotePath, localPath, null);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(
                    $"DownloadFileTaskAsync (download failed): {remotePath} Additional informations : {ex.Message}");
                return new Tuple<string, string, Exception>(remotePath, null, ex);
            }
        }