コード例 #1
0
ファイル: ChunkDownloader.cs プロジェクト: aslyr/Downloader
 private async Task DownloadChunk(Request downloadRequest, CancellationToken token)
 {
     token.ThrowIfCancellationRequested();
     if (Chunk.IsDownloadCompleted() == false)
     {
         HttpWebRequest request = downloadRequest.GetRequest();
         SetRequestRange(request);
         using HttpWebResponse downloadResponse = request.GetResponse() as HttpWebResponse;
         if (downloadResponse.StatusCode == HttpStatusCode.OK ||
             downloadResponse.StatusCode == HttpStatusCode.PartialContent ||
             downloadResponse.StatusCode == HttpStatusCode.Created ||
             downloadResponse.StatusCode == HttpStatusCode.Accepted ||
             downloadResponse.StatusCode == HttpStatusCode.ResetContent)
         {
             Configuration.RequestConfiguration.CookieContainer = request.CookieContainer;
             using Stream responseStream = downloadResponse?.GetResponseStream();
             if (responseStream != null)
             {
                 using ThrottledStream destinationStream =
                           new ThrottledStream(responseStream, Configuration.MaximumSpeedPerChunk);
                 await ReadStream(destinationStream, token).ConfigureAwait(false);
             }
         }
         else
         {
             throw new WebException($"Download response status was {downloadResponse.StatusCode}: {downloadResponse.StatusDescription}");
         }
     }
 }
コード例 #2
0
        private async Task DownloadChunk(Request downloadRequest, long maximumSpeed, CancellationToken token)
        {
            if (token.IsCancellationRequested ||
                Chunk.IsDownloadCompleted())
            {
                return;
            }

            if (Chunk.IsValidPosition() == false)
            {
                Chunk.Position = 0;
            }

            HttpWebRequest request = downloadRequest.GetRequest();

            request.AddRange(Chunk.Start + Chunk.Position, Chunk.End);
            using HttpWebResponse downloadResponse = request.GetResponse() as HttpWebResponse;
            using Stream responseStream            = downloadResponse?.GetResponseStream();

            if (responseStream != null)
            {
                using ThrottledStream destinationStream = new ThrottledStream(responseStream, maximumSpeed);
                await ReadStream(destinationStream, token);
            }
        }
コード例 #3
0
        private async Task DownloadChunk(Request downloadRequest, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            if (Chunk.IsDownloadCompleted() == false)
            {
                HttpWebRequest request = downloadRequest.GetRequest();
                SetRequestRange(request);
                using HttpWebResponse downloadResponse = request.GetResponse() as HttpWebResponse;
                using Stream responseStream            = downloadResponse?.GetResponseStream();

                if (responseStream != null)
                {
                    using ThrottledStream destinationStream =
                              new ThrottledStream(responseStream, Configuration.MaximumSpeedPerChunk);
                    await ReadStream(destinationStream, token).ConfigureAwait(false);
                }
            }
        }
コード例 #4
0
        protected async Task <Chunk> DownloadChunk(Uri address, Chunk chunk, CancellationToken token)
        {
            try
            {
                if (token.IsCancellationRequested)
                {
                    return(chunk);
                }

                var request = GetRequest("GET", address);
                if (chunk.Start + chunk.Position >= chunk.End && chunk.Data?.LongLength == chunk.Length)
                {
                    return(chunk); // downloaded completely before
                }
                if (chunk.Position >= chunk.Length && chunk.Data == null)
                {
                    chunk.Position = 0; // downloaded again and reset chunk position
                }
                request.AddRange(chunk.Start + chunk.Position, chunk.End);

                using var httpWebResponse = request.GetResponse() as HttpWebResponse;
                if (httpWebResponse == null)
                {
                    return(chunk);
                }

                var stream            = httpWebResponse.GetResponseStream();
                var destinationStream = new ThrottledStream(stream,
                                                            Package.Options.ParallelDownload
                    ? Package.Options.MaximumBytesPerSecond / Package.Options.ChunkCount
                    : Package.Options.MaximumBytesPerSecond);
                using (stream)
                {
                    if (stream == null)
                    {
                        return(chunk);
                    }

                    if (Package.Options.OnTheFlyDownload)
                    {
                        await ReadStreamOnTheFly(destinationStream, chunk, token);
                    }
                    else
                    {
                        await ReadStreamOnTheFile(destinationStream, chunk, token);
                    }
                }

                return(chunk);
            }
            catch (TaskCanceledException) // when stream reader timeout occured
            {
                // re-request
                if (token.IsCancellationRequested == false)
                {
                    await DownloadChunk(address, chunk, token);
                }
            }
            catch (WebException) when(token.IsCancellationRequested == false &&
                                      chunk.FailoverCount++ <= Package.Options.MaxTryAgainOnFailover)  // when the host forcibly closed the connection.
            {
                await Task.Delay(Package.Options.Timeout, token);

                chunk.Checkpoint();
                // re-request
                await DownloadChunk(address, chunk, token);
            }
            catch (Exception e) when(token.IsCancellationRequested == false &&
                                     chunk.FailoverCount++ <= Package.Options.MaxTryAgainOnFailover &&
                                     (e.HasSource("System.Net.Http") ||
                                      e.HasSource("System.Net.Sockets") ||
                                      e.HasSource("System.Net.Security") ||
                                      e.InnerException is SocketException))
            {
                // wait and decrease speed to low pressure on host
                Package.Options.Timeout += chunk.CanContinue() ? 0 : 500;
                chunk.Checkpoint();
                await Task.Delay(Package.Options.Timeout, token);

                // re-request
                await DownloadChunk(address, chunk, token);
            }
            catch (Exception e) // Maybe no internet!
            {
                OnDownloadFileCompleted(new AsyncCompletedEventArgs(e, false, Package));
                Debugger.Break();
            }

            return(chunk);
        }