/* * GNU AFFERO GENERAL PUBLIC LICENSE * Version 3, 19 November 2007 * Copyright (C) 2007 Free Software Foundation, Inc. * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. */ using System; using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; namespace UVtools.Core.Extensions; public static class NetworkExtensions { public static readonly HttpClient HttpClient = new() { DefaultRequestHeaders = { UserAgent = { new ProductInfoHeaderValue(About.Software, About.VersionStr) } } }; public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<(long total, long bytes)>? progress = null, CancellationToken cancellationToken = default) { // Get the http headers first to examine the content length var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken); var contentLength = response.Content.Headers.ContentLength; await using var download = await response.Content.ReadAsStreamAsync(cancellationToken); // Ignore progress reporting when no progress reporter was // passed or when the content length is unknown if (progress is null || !contentLength.HasValue) { await download.CopyToAsync(destination, cancellationToken); return response; } // Convert absolute progress (bytes downloaded) into relative progress (0% - 100%) var relativeProgress = new Progress(downloadedBytes => progress.Report(new (contentLength.Value, downloadedBytes))); // Use extension method to report progress while downloading await download.CopyToAsync(destination, relativeProgress, cancellationToken); progress.Report(new(contentLength.Value, contentLength.Value)); return response; } public static async Task DownloadAsync(this HttpClient client, string requestUri, string destinationFilePath, IProgress<(long total, long bytes)>? progress = null, CancellationToken cancellationToken = default) { await using var stream = File.Open(destinationFilePath, FileMode.Create, FileAccess.Write); return await DownloadAsync(client, requestUri, stream, progress, cancellationToken); } public static async Task DownloadAsync(string requestUri, Stream destination, IProgress<(long total, long bytes)>? progress = null, CancellationToken cancellationToken = default) => await HttpClient.DownloadAsync(requestUri, destination, progress, cancellationToken); public static async Task DownloadAsync(string requestUri, string destinationFilePath, IProgress<(long total, long bytes)>? progress = null, CancellationToken cancellationToken = default) => await HttpClient.DownloadAsync(requestUri, destinationFilePath, progress, cancellationToken); }