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和进度条上传?这似乎是一个适度的需求.还是我应该使用另一个班级?非常感谢.
假设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上,您还需要禁用AllowAutoRedirect
WP8 ,因为WP8在处理重定向的帖子时存在一个错误(解决方法是先发出HEAD,获取重定向的URL,然后使用将该帖子发送到最终URL AllowAutoRedirect = false
)。