예제 #1
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);
        }
예제 #2
0
 public ChunkDownloader(Chunk chunk, DownloadConfiguration config)
 {
     Chunk         = chunk;
     Configuration = config;
 }