如何使用HttpClient PostAsync计算进度?

在我的Windowsapp store应用程序(c#)中,我需要将MultipartFormDataContent (一些字符串内容和一些文件)上传到服务器并在响应时获取一个巨大的文件。 问题 – 我不能使用BackgroundDownloaders 。 我只能使用一个请求。

我使用HttpClient.PostAsync方法:

  using (var client = new HttpClient(httpClientHandler)) { using (var content = new MultipartFormDataContent()) { content.Add(...); // prepare all strings and files content try { using (var response = await client.PostAsync(url, content)) { if (response.StatusCode == HttpStatusCode.OK) { var inputBytes = await response.Content.ReadAsByteArrayAsync(); // some operations with inputBytes } ...... } } } } 

我的问题是:如何计算此操作的进度?

注意:我的目标 – Windows 8.而且我无法使用Windows.Web.Http.HttpClient (最低支持的客户端Windows 8.1)。 只有System.Net.Http.HttpClient

我遇到了同样的问题。 我通过实现自定义HttpContent修复它。 我使用此对象来跟踪上传进度的百分比,您可以添加事件并收听它。 您应该自定义SerializeToStreamAsync方法。

 internal class ProgressableStreamContent : HttpContent { private const int defaultBufferSize = 4096; private Stream content; private int bufferSize; private bool contentConsumed; private Download downloader; public ProgressableStreamContent(Stream content, Download downloader) : this(content, defaultBufferSize, downloader) {} public ProgressableStreamContent(Stream content, int bufferSize, Download downloader) { if(content == null) { throw new ArgumentNullException("content"); } if(bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } this.content = content; this.bufferSize = bufferSize; this.downloader = downloader; } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { Contract.Assert(stream != null); PrepareContent(); return Task.Run(() => { var buffer = new Byte[this.bufferSize]; var size = content.Length; var uploaded = 0; downloader.ChangeState(DownloadState.PendingUpload); using(content) while(true) { var length = content.Read(buffer, 0, buffer.Length); if(length <= 0) break; downloader.Uploaded = uploaded += length; stream.Write(buffer, 0, length); downloader.ChangeState(DownloadState.Uploading); } downloader.ChangeState(DownloadState.PendingResponse); }); } protected override bool TryComputeLength(out long length) { length = content.Length; return true; } protected override void Dispose(bool disposing) { if(disposing) { content.Dispose(); } base.Dispose(disposing); } private void PrepareContent() { if(contentConsumed) { // If the content needs to be written to a target stream a 2nd time, then the stream must support // seeking (eg a FileStream), otherwise the stream can't be copied a second time to a target // stream (eg a NetworkStream). if(content.CanSeek) { content.Position = 0; } else { throw new InvalidOperationException("SR.net_http_content_stream_already_read"); } } contentConsumed = true; } } 

仅供参考:

 public interface IDownload { event EventHandler StateChanged; event EventHandler Completed; DownloadState State { get; } Guid Id { get; } string Uri { get; } long Filesize { get; } long Downloaded { get; } Task DownloadAsync(); } 

WebAPI Client nuget有一些用于执行此操作的类。 看一下ProgressMessageHandler 。 它是一个PCL库,因此它应该适用于Windowsapp store应用程序。