public ParallelHttpClient(bool IgnoreCompression = false) { httpClient = new HttpClient( new HttpClientHandler() { AutomaticDecompression = IgnoreCompression ? DecompressionMethods.None : DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.None, UseCookies = true, MaxConnectionsPerServer = 16, AllowAutoRedirect = true }); httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", App.UserAgent); Status = ParallelHttpClientStatus.Idle; }
public bool DownloadFile(string input, string output, string customMessage = "", long startOffset = -1, long endOffset = -1, CancellationToken token = new CancellationToken()) { if (string.IsNullOrEmpty(customMessage)) { customMessage = $"Downloading {Path.GetFileName(output)}"; } Status = ParallelHttpClientStatus.Downloading; bool ret; while (!(ret = GetRemoteStreamResponse(input, output, startOffset, endOffset, customMessage, token, false))) { #if DEBUG Console.WriteLine("Retrying..."); #endif Thread.Sleep(1000); } return(ret); }
public bool DownloadStream(string input, MemoryStream output, CancellationToken token = new CancellationToken(), long startOffset = -1, long endOffset = -1, string customMessage = "") { if (string.IsNullOrEmpty(customMessage)) { customMessage = $"Downloading to stream"; } Status = ParallelHttpClientStatus.Downloading; bool ret; localStream = output; while (!(ret = GetRemoteStreamResponse(input, @"buffer", startOffset, endOffset, customMessage, token, true))) { #if DEBUG Console.WriteLine("Retrying..."); #endif Thread.Sleep(1000); } return(ret); }
public void MergePartialChunks() { if (CheckExistingPartialChunksSize() != downloadPartialSize) { #if DEBUG Console.WriteLine("Download is not completed yet! Please do DownloadFileMultipleSession() and wait it for finish!"); #endif return; } if (downloadPartialToken.IsCancellationRequested) { #if DEBUG Console.WriteLine("Cannot do merging since token is cancelled!"); #endif return; } Status = ParallelHttpClientStatus.Merging; Task.Run(() => GetPartialDownloadEvents()); string chunkFileName; FileStream chunkFile; byte[] buffer = new byte[67108864]; int read; long totalRead = 0; var sw = Stopwatch.StartNew(); FileInfo fileInfo = new FileInfo($"{downloadPartialOutputPath}_tmp"); using (FileStream fs = fileInfo.Create()) { for (int i = 0; i < downloadThread; i++) { chunkFileName = string.Format("{0}.{1:000}", downloadPartialOutputPath, i + 1); using (chunkFile = new FileStream(chunkFileName, FileMode.Open, FileAccess.Read)) { while ((read = chunkFile.Read(buffer, 0, buffer.Length)) > 0) { downloadPartialToken.ThrowIfCancellationRequested(); fs.Write(buffer, 0, read); totalRead += read; PartialOnProgressChanged(new PartialDownloadProgressChanged(totalRead, 0, downloadPartialSize, sw.Elapsed.TotalSeconds) { Message = "Merging Chunks", CurrentReceived = read }); } chunkFile.Dispose(); } File.Delete(chunkFileName); } } if (File.Exists(downloadPartialOutputPath)) { File.Delete(downloadPartialOutputPath); } fileInfo.MoveTo(downloadPartialOutputPath); sw.Stop(); Status = ParallelHttpClientStatus.Idle; }
public void DownloadFileMultipleSession(string input, string output, string customMessage = "", int threads = 1, CancellationToken token = new CancellationToken()) { downloadThread = threads; downloadPartialToken = token; downloadPartialInputPath = input; downloadPartialOutputPath = output; OnCompleted(new DownloadProgressCompleted() { DownloadCompleted = false }); downloadPartialSize = GetContentLength(downloadPartialInputPath) ?? 0; long startContent, endContent; segmentDownloadTask = new List <Task>(); segmentDownloadProperties = new List <SegmentDownloadProperties>(); List <ChunkRanges> chunkRanges = new List <ChunkRanges>(); long partitionSize = (long)Math.Ceiling((double)downloadPartialSize / downloadThread); for (int i = 0; i < downloadThread; i++) { startContent = i * (downloadPartialSize / downloadThread); endContent = i + 1 == downloadThread ? downloadPartialSize : ((i + 1) * (downloadPartialSize / downloadThread)) - 1; segmentDownloadProperties.Add(new SegmentDownloadProperties(0, 0, 0, 0) { CurrentReceived = 0, StartRange = startContent, EndRange = endContent, PartRange = i }); } OnResumabilityChanged(new DownloadStatusChanged(true)); #if DEBUG Console.WriteLine($"\r\nStarting Partial Download!\r\n\tTotal Size: {BpUtility.ToBytesCount(downloadPartialSize)} ({downloadPartialSize} bytes)\r\n\tThreads/Chunks: {downloadThread}"); #endif Status = ParallelHttpClientStatus.Downloading; try { foreach (SegmentDownloadProperties j in segmentDownloadProperties) { segmentDownloadTask.Add(Task.Run(async() => { while (!await GetPartialSessionStream(j)) { #if DEBUG Console.WriteLine($"Retrying to connect for chunk no: {j.PartRange + 1}..."); #endif Thread.Sleep(1000); } }, downloadPartialToken)); } Task.Run(() => GetPartialDownloadEvents()); Task.WhenAll(segmentDownloadTask).GetAwaiter().GetResult(); } catch (Exception ex) { #if DEBUG Console.WriteLine($"{ex}"); #endif } if (!downloadPartialToken.IsCancellationRequested) { try { MergePartialChunks(); } catch (OperationCanceledException ex) { #if DEBUG Console.WriteLine("Merging cancelled!"); #endif throw new OperationCanceledException("", ex); } } else { segmentDownloadTask.Clear(); #if DEBUG Console.WriteLine("Download cancelled!"); #endif throw new OperationCanceledException(); } segmentDownloadTask.Clear(); #if DEBUG Console.WriteLine(" Done!"); #endif Status = ParallelHttpClientStatus.Idle; }