且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

HttpClient-下载之前下载文件的大小

更新时间:2023-01-05 13:46:37

您可以查看服务器返回的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();
}