HttpClient上传的进度条

thu*_*und 7 wpf upload portable-class-library progress-bar dotnet-httpclient

我想在WPF中使用进度条运行异步上传(最好使用PCL在Xamarin和SL中重用代码.)

我一直在尝试使用System.Net.HttpClient.不幸的是,PutAsync不提供任何进度通知.(我知道它适用于Windows.Web.Http.HttpClient,但这不适用于WPF,也不适用于PCL).

对于下载,它非常容易实现自己的进度条,如所描述这里.您只需传递ResponseHeadersRead选项,该选项会在返回标题后立即使用该流,然后您可以在块中按块读取它,随时增加进度条.但是对于上传,这种技术不起作用 - 您需要一次性将所有上传数据传递给PutAsync,因此没有机会增加您的计数器.

我也想知道如何使用HttpClient.SendAsync.我所希望我可以把这个像一个异步HttpWebRequest的(其中如你所描述的写入HttpWebRequest.GetRequestStream可以增加计数器在这里).但不幸的是HttpClient.SendAsync不会给你可写的流,所以这不起作用.

那么HttpClient是否支持使用非阻止UI和进度条上传?这似乎是一个适度的需求.还是我应该使用另一个班级?非常感谢.

The*_*ESJ 5

假设HttpClient(和底层网络堆栈)没有缓冲,您应该可以通过重写来做到这一点HttpContent.SerializeToStreamAsync。您可以执行以下操作:

        const int chunkSize = 4096;
        readonly byte[] bytes;
        readonly Action<double> progress;

        protected override async Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context)
        {
            for (int i = 0; i < this.bytes.Length; i += chunkSize)
            {
                await stream.WriteAsync(this.bytes, i, Math.Min(chunkSize, this.bytes.Length - i));
                this.progress(100.0 * i / this.bytes.Length);
            }
        }
Run Code Online (Sandbox Code Playgroud)

为了避免被缓冲,HttpClient您需要提供内容长度(例如:实现HttpContent.TryComputeLength或设置标题)或enable HttpRequestHeaders.TransferEncodingChunked。这是必需的,因为否则HttpClient无法确定内容长度标头,因此它首先将整个内容读入内存。

在电话8上,您还需要禁用AllowAutoRedirectWP8 ,因为WP8在处理重定向的帖子时存在一个错误(解决方法是先发出HEAD,获取重定向的URL,然后使用将该帖子发送到最终URL AllowAutoRedirect = false)。