Example #1
0
        /// <summary>
        /// Get properties of file asynchronously.
        /// </summary>
        /// <returns>
        /// FileProperties in asynchronous task.
        /// </returns>
        /// <param name="uri">URI of file.</param>
        private static async Task <FileProperties> GetFilePropertiesAsync(string uri)
        {
            try
            {
                using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
                {
                    request.SetTimeout(TimeSpan.FromSeconds(Singleton.Settings.TimeoutSeconds));
                    request.Headers.Range = new RangeHeaderValue(from: 0, to: 0);
                    request.Headers.Add("User-Agent", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName));
                    string[] s = new Uri(uri).UserInfo.Split(':');

                    if (s != null && s.Length == 2)
                    {
                        Console.WriteLine($"{uri}: Authenticating with Basic authentication...");
                        BasicAuthentication(request, s);
                    }

                    using (var response = await HttpClient.SendAsync(request))
                    {
                        response.EnsureSuccessStatusCode();
                        FileProperties properties = new FileProperties();

                        if (response.Content.Headers.ContentDisposition == null)
                        {
                            if (response.Content.Headers.TryGetValues("Content-Disposition", out IEnumerable <string> contentDisposition))
                            {
                                response.Content.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(contentDisposition.ToArray()[0].TrimEnd(';').Replace("\"", ""));
                            }
                        }

                        properties.Name = response.Content.Headers?.ContentDisposition?.FileName ?? response.RequestMessage.RequestUri.Segments.LastOrDefault();

                        if (response.Content.Headers.TryGetValues(@"Content-Range", out IEnumerable <string> range))
                        {
                            properties.Size = long.Parse(System.Text.RegularExpressions.Regex.Match(range.Single(), @"(?<=^bytes\s[0-9]+\-[0-9]+/)[0-9]+$").Value);
                        }
                        else
                        {
                            properties.Size = 0;
                        }

                        properties.RangeAccepted = response.Headers.AcceptRanges.Contains("bytes");
                        properties.ContentStream = await response.Content.ReadAsStreamAsync();

                        return(properties);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
Example #2
0
        /// <summary>
        /// Prepare file for download asynchronously.
        /// </summary>
        /// <returns>
        /// Boolean of whether preparation is successful in asynchronous task.
        /// </returns>
        /// <param name="uri">URI of file.</param>
        public async Task <bool> LoadFileAsync(string uri)
        {
            try
            {
                int            retry      = Singleton.Settings.TimeoutRetries;
                FileProperties properties = null;

                while (retry >= 0 && properties == null)
                {
                    await Task.Delay(TimeSpan.FromSeconds((Singleton.Settings.TimeoutRetries - retry) * Singleton.Settings.LinearBackoffInterval));

                    try
                    {
                        properties = await GetFilePropertiesAsync(uri);
                    }
                    catch (TimeoutException te)
                    {
                        retry--;
                        Console.WriteLine($"{uri}: {te.GetType().FullName}: {te.Message}");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"{uri}: {e.GetType().FullName}: {e.Message}");
                        return(false);
                    }
                }

                _filePath = $"{Singleton.Settings.DownloadLocation}/{properties.Name}";

                if (properties == null)
                {
                    return(false);
                }
                else if (properties.Name == "/")
                {
                    Console.WriteLine($"{uri}: URI is not a file");
                    return(false);
                }
                else if (properties.Size == 0)
                {
                    return(true);
                }

                // Uncomment to debug properties
                //var dump = ObjectDumper.Dump(properties);
                //Console.WriteLine(dump);
                if (!properties.RangeAccepted)
                {
                    Console.WriteLine($"{uri}: Segmented downloading not supported, continuing with normal download...");
                }
                int count = 0;

                foreach (var(start, end) in SegmentPosition(properties.Size, properties.RangeAccepted ? Singleton.Settings.SegmentsPerFile : 1))
                {
                    retry = Singleton.Settings.TimeoutRetries;
                    count++;
                    bool isSuccessStatusCode = false;

                    while (retry >= 0 && !isSuccessStatusCode)
                    {
                        await Task.Delay(TimeSpan.FromSeconds((Singleton.Settings.TimeoutRetries - retry) * Singleton.Settings.LinearBackoffInterval));

                        Console.WriteLine($"{uri}: Building segment {count}...");

                        try
                        {
                            using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
                            {
                                string[] s = new Uri(uri).UserInfo.Split(':');

                                if (s != null && s.Length == 2)
                                {
                                    Console.WriteLine($"{uri}: Authenticating with Basic authentication...");
                                    BasicAuthentication(request, s);
                                }

                                request.SetTimeout(TimeSpan.FromSeconds(Singleton.Settings.TimeoutSeconds));
                                request.Headers.Range = new RangeHeaderValue(start, end);
                                request.Headers.Add("User-Agent", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName));
                                var responseMessage = await HttpClient.SendAsync(request);

                                isSuccessStatusCode = responseMessage.IsSuccessStatusCode;
                                responseMessage.EnsureSuccessStatusCode();
                                _fileSegments.Add(new FileSegment
                                {
                                    ID        = count,
                                    Start     = start,
                                    End       = end,
                                    BytesRead = 0,
                                    Content   = await responseMessage.Content.ReadAsStreamAsync()
                                });
                            }
                        }
                        catch (TimeoutException te)
                        {
                            retry--;
                            Console.WriteLine($"{uri}: {te.GetType().FullName}: {te.Message}");
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"{uri}: {e.GetType().FullName}: {e.Message}");
                        }
                    }
                }

                // Uncomment to debug fileSegments
                //dump = ObjectDumper.Dump(fileSegments);
                //Console.WriteLine(dump);
            }
            catch (Exception e)
            {
                Console.WriteLine($"{uri}: {e.GetType().FullName}: {e.Message}");
                return(false);
            }

            return(true);
        }