HttpClient上传进度条 [英] Progress bar for HttpClient uploading

查看:197
本文介绍了HttpClient上传进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to run asynchronous uploads with a progress bar in WPF (and preferably use PCL for code reuse in Xamarin and SL too.)

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

I've been trying to use System.Net.HttpClient. Unfortunately, PutAsync doesn't provide any progress notifications. (I know that it does for Windows.Web.Http.HttpClient, but that's not available for WPF, nor in the PCL).

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

For downloading, its fairly easy to implement your own progress bar, as described here. You just pass the ResponseHeadersRead option, which makes the stream available as soon as the headers are returned, and then you read it in chunk by chunk, incrementing your progress bar as you go. But for uploading, this technique doesn't work - you need to pass all your upload data into PutAsync in one go, so there's no chance to increment your counter.

我还想知道是否使用HttpClient.SendAsync.我希望我可以像对待异步HttpWebRequest一样对待它(在其中,您可以按照

I've also wondered about using HttpClient.SendAsync instead. I'd hoped I could just treat this like an asynchronous HttpWebRequest (in which you can increment the counter as you write to the HttpWebRequest.GetRequestStream as described here). But unfortunately HttpClient.SendAsync doesn't give you writeable stream, so that doesn't work.

那么HttpClient是否支持使用非阻塞UI和进度条进行上传?这似乎是一个适度的需求.还是我应该使用其他课程?非常感谢.

So does HttpClient support uploads with a non-blocked UI and a progress bar? It seems like a modest need. Or is there another class I should be using? Thanks very much.

推荐答案

假定HttpClient(和基础网络堆栈)没有缓冲,您应该可以通过覆盖HttpContent.SerializeToStreamAsync来做到这一点.您可以执行以下操作:

Assuming that HttpClient (and underlying network stack) isn't buffering you should be able to do this by overriding HttpContent.SerializeToStreamAsync. You can do something like the following:

        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);
            }
        }

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

In order to avoid being buffered by HttpClient you either need to provide a content length (eg: implement HttpContent.TryComputeLength, or set the header) or enable HttpRequestHeaders.TransferEncodingChunked. This is necessary because otherwise HttpClient can't determine the content length header, so it reads in the entire content to memory first.

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

On the phone 8 you also need to disable AllowAutoRedirect because WP8 has a bug in the way it handles redirected posts (workaround is to issue a HEAD first, get the redirected URL, then send the post to the final URL with AllowAutoRedirect = false).

这篇关于HttpClient上传进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆