HttpClient-下载之前下载文件的大小 [英] HttpClient - Size of downloading file before download

查看:551
本文介绍了HttpClient-下载之前下载文件的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过进度条实施文件下载。我为此问题使用了 IAsyncOperationWithProgress ,具体来说是此代码。一切正常,但我只收到已接收/下载的字节数。但是我需要计算百分比部分以显示进度。这意味着我需要在开始下载时就知道总字节数,而我没有找到有效执行此操作的方法。

I'm implementing download of files with progress bar. I'm using IAsyncOperationWithProgress for this issue, concretely this code. It is working nice, but I'm receiving only count of bytes that were received/downloaded. But I need calculate percentual part for showing progress. That means I need to know total count of bytes at the start of downloading and I didn't find way how to do this effectively.

以下代码可以解决进度报告。我尝试使用 responseStream.Length 获取流的长度,但出现错误此流不支持搜索操作。

Following code resolves progress reporting. I tried to get stream length with responseStream.Length but error "This stream does not support seek operations." was thrown.

static async Task<byte[]> GetByteArratTaskProvider(Task<HttpResponseMessage> httpOperation, CancellationToken token, IProgress<int> progressCallback)
        {
            int offset = 0;
            int streamLength = 0;
            var result = new List<byte>();

            var responseBuffer = new byte[500];

            // Execute the http request and get the initial response
            // NOTE: We might receive a network error here
            var httpInitialResponse = await httpOperation;

            using (var responseStream = await httpInitialResponse.Content.ReadAsStreamAsync())
            {
                int read;

                do
                {
                    if (token.IsCancellationRequested)
                    {
                        token.ThrowIfCancellationRequested();
                    }

                    read = await responseStream.ReadAsync(responseBuffer, 0, responseBuffer.Length);

                    result.AddRange(responseBuffer);

                    offset += read;
                    // here I want to send percents of downloaded data
                    // offset / (totalSize / 100)
                    progressCallback.Report(offset);

                } while (read != 0);
            }

            return result.ToArray();
        }

您是否知道如何处理此问题?或者,您还有其他方法如何通过HttpClient下载带有进度报告的文件?我也尝试使用 BackgroundDownloader ,但这对我来说还不够。谢谢。

Do you have any idea how to deal with this issue? Or do you have some another way how to download files with progress reporting through HttpClient? I tried to use BackgroundDownloader as well but it was not sufficient for me. Thank you.

推荐答案

您可以查看服务器返回的Content-Length标头的值,该标头存储在您的 httpInitialResponse.Content.Headers 中的大小写。您必须在集合中找到带有相应键(即 Content-Length)的标头

You can look at the value of the Content-Length header returned by the server, which is stored in your case in httpInitialResponse.Content.Headers. You'll have to find the header in the collection with the corresponding key (i.e. "Content-Length")

您可以这样做,例如:

int length = int.Parse(httpInitialResponse.Content.Headers.First(h => h.Key.Equals("Content-Length")).Value.First());

(您必须先确保服务器已发送Content-Length标头,否则应确保

(You have to make sure first that a Content-Length header has been sent by the server, otherwise the line above will fail with an exception)

您的代码如下所示:

static async Task<byte[]> GetByteArrayTaskProvider(Task<HttpResponseMessage> httpOperation, CancellationToken token, IProgress<int> progressCallback)
{
    int offset = 0;
    int streamLength = 0;
    var result = new List<byte>();

    var responseBuffer = new byte[500];

    // Execute the http request and get the initial response
    // NOTE: We might receive a network error here
    var httpInitialResponse = await httpOperation;
    var totalValueAsString = httpInitialResponse.Content.Headers.SingleOrDefault(h => h.Key.Equals("Content-Length"))?.Value?.First());
    int? totalValue = totalValueAsString != null ? int.Parse(totalValueAsString) : null;

    using (var responseStream = await httpInitialResponse.Content.ReadAsStreamAsync())
    {
       int read;
       do
       {
           if (token.IsCancellationRequested)
           {
              token.ThrowIfCancellationRequested();
           }

           read = await responseStream.ReadAsync(responseBuffer, 0, responseBuffer.Length);
           result.AddRange(responseBuffer);

           offset += read;
           if (totalSize.HasValue)
           {
              progressCallback.Report(offset * 100 / totalSize);
           }
           //for else you could send back the offset, but the code would become to complex in this method and outside of it. The logic for "supports progress reporting" should be somewhere else, to keep methods simple and non-multi-purpose (I would create a method for with bytes progress and another for percentage progress)
       } while (read != 0);
    }
    return result.ToArray();
}

这篇关于HttpClient-下载之前下载文件的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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