在 .NET 4.5 中引入的 IProgress<T>
接口允许处理异步进度报告,从而为使用 HttpClient 下载文件实现进度条功能。
IProgress<T>
的扩展方法为 HttpClient 的 DownloadAsync
操作创建一个扩展方法,该方法接受 IProgress<float>
实现作为参数。此实现将使用下载状态更新进度条或 UI。
<code class="language-csharp">public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<float> progress = null, CancellationToken cancellationToken = default) { // 首先获取 http 头信息以检查内容长度 using (var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead)) { var contentLength = response.Content.Headers.ContentLength; using (var download = await response.Content.ReadAsStreamAsync(cancellationToken)) { // 未传递进度报告器或内容长度未知时忽略进度报告 if (progress == null || !contentLength.HasValue) { await download.CopyToAsync(destination); return; } // 将绝对进度(已下载字节数)转换为相对进度(0% - 100%) var relativeProgress = new Progress<long>(totalBytes => progress.Report((float)totalBytes / contentLength.Value)); // 使用扩展方法在下载时报告进度 await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken); progress.Report(1); // 报告100%完成 } } }</code>
在此方法中,progress.Report()
方法会将当前下载进度(百分比)传递给您的 IProgress<float>
实现,从而允许它相应地更新进度条或其他 UI 元素。
为了在将数据写入目标流时处理实际的进度报告,请考虑为 Stream 类创建一个扩展方法。
<code class="language-csharp">public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default) { if (source == null) throw new ArgumentNullException(nameof(source)); if (!source.CanRead) throw new ArgumentException("必须可读", nameof(source)); if (destination == null) throw new ArgumentNullException(nameof(destination)); if (!destination.CanWrite) throw new ArgumentException("必须可写", nameof(destination)); if (bufferSize < 0) throw new ArgumentOutOfRangeException(nameof(bufferSize)); var buffer = new byte[bufferSize]; long totalBytesRead = 0; int bytesRead; while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) { await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; progress?.Report(totalBytesRead); } }</code>
此扩展方法监视写入目标流的字节数,并使用传入的 IProgress<long>
实现报告进度。
通过组合这些扩展方法,您可以轻松地为使用 HttpClient 的文件下载操作实现进度条功能。
以上是如何在.NET中使用HttpClient实现进度条?的详细内容。更多信息请关注PHP中文网其他相关文章!