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); }
public ChunkDownloader(Chunk chunk, DownloadConfiguration config) { Chunk = chunk; Configuration = config; }