using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace Млаумчерб.Клиент; public record struct NetworkTransferResult(long BytesTotal, long BytesTransferred, long BytesPerSecond) { public override string ToString() { return $"transferred {BytesTransferred}/{BytesTotal} bytes ({BytesPerSecond}) bps"; } } public class NetworkTransferTask { public Task Task { get; private set; } public Progress Progress { get; private set; } private Stream _src; private Stream _dst; private CancellationTokenSource _cts; private DTLib.Timer _timer; public NetworkTransferTask(Stream src, Stream dst) { _src = src; _dst = dst; _cts = new CancellationTokenSource(); Progress = new Progress(); _timer = new(true, 1000, ReportProgress); Task = Task.CompletedTask; } public void Start() { _timer.Start(); Task = _src.CopyToAsync(_dst); _timer.Stop(); } public void Stop() { _cts.Cancel(); _timer.Stop(); } private long previousBytesTransferred; private void ReportProgress() { long bytesTotal = _src.Length, bytesTransferred = _src.Position; long bytesPerSecond = bytesTransferred - previousBytesTransferred; previousBytesTransferred = bytesTransferred; ((IProgress)Progress).Report(new NetworkTransferResult(bytesTotal, bytesTransferred, bytesPerSecond)); } public TaskAwaiter GetAwaiter() => Task.GetAwaiter(); } public static class NetworkHelper { private static HttpClient http = new(); public static NetworkTransferTask DownloadHTTPFileAsync(string url, Stream destinationStream) { var sourceStream = http.GetStreamAsync(url).GetAwaiter().GetResult(); NetworkTransferTask task = new(sourceStream, destinationStream); task.Start(); return task; } }