C#-如何计算下载速度和估计的下载时间

时间:2020-03-15 14:48:48

标签: c# httpclient

这是我的HttpClientDownloadWithProgress类:

public class HttpClientDownloadWithProgress : IDisposable
{
    private readonly string _downloadUrl;
    private readonly string _destinationFilePath;

    private HttpClient _httpClient;

    public delegate void ProgressChangedHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage);

    public event ProgressChangedHandler ProgressChanged;

    public HttpClientDownloadWithProgress(string downloadUrl, string destinationFilePath)
    {
        _downloadUrl = downloadUrl;
        _destinationFilePath = destinationFilePath;
    }

    public async Task StartDownload()
    {
        _httpClient = new HttpClient { Timeout = TimeSpan.FromDays(1) };

        using (var response = await _httpClient.GetAsync(_downloadUrl, HttpCompletionOption.ResponseHeadersRead))
            await DownloadFileFromHttpResponseMessage(response);
    }

    private async Task DownloadFileFromHttpResponseMessage(HttpResponseMessage response)
    {
        response.EnsureSuccessStatusCode();

        var totalBytes = response.Content.Headers.ContentLength;

        using (var contentStream = await response.Content.ReadAsStreamAsync())
            await ProcessContentStream(totalBytes, contentStream);
    }

    private async Task ProcessContentStream(long? totalDownloadSize, Stream contentStream)
    {
        var totalBytesRead = 0L;
        var readCount = 0L;
        var buffer = new byte[8192];
        var isMoreToRead = true;

        using (var fileStream = new FileStream(_destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
        {
            do
            {
                var bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length);
                if (bytesRead == 0)
                {
                    isMoreToRead = false;
                    TriggerProgressChanged(totalDownloadSize, totalBytesRead);
                    continue;
                }

                await fileStream.WriteAsync(buffer, 0, bytesRead);

                totalBytesRead += bytesRead;
                readCount += 1;

                if (readCount % 100 == 0)
                    TriggerProgressChanged(totalDownloadSize, totalBytesRead);
            }
            while (isMoreToRead);
        }
    }

    private void TriggerProgressChanged(long? totalDownloadSize, long totalBytesRead)
    {
        if (ProgressChanged == null)
            return;

        double? progressPercentage = null;
        if (totalDownloadSize.HasValue)
            progressPercentage = Math.Round((double)totalBytesRead / totalDownloadSize.Value * 100, 2);

        ProgressChanged(totalDownloadSize, totalBytesRead, progressPercentage);
    }

    public void Dispose()
    {
        _httpClient?.Dispose();
    }
}

以下是我使用它下载文件并显示进度百分比的方法:

public async void DownloadGame()
{
    string gamezipUrl = GameUpdaterModel.serverUrl + "versions/" + GameUpdaterModel.DetermineOS().ToString().ToLower() + "/current/" + GameUpdaterModel.versionsList.First().version + ".zip";

    var destinationFilePath = GameUpdaterModel.gameDir + "\\7.zip";
    int pp;

    using (var client = new HttpClientDownloadWithProgress(gamezipUrl, destinationFilePath))
    {
        client.ProgressChanged += (totalFileSize, totalBytesDownloaded, progressPercentage) => {
            MainWindowViewModel.Instance.ProgressStatus = "Downloading: " + Convert.ToInt32(progressPercentage) + "%"+ "("+ totalBytesDownloaded + "/"+totalFileSize+")";
        };

        await client.StartDownload();
    }
}

我的问题是如何计算和显示当前下载速度以及估计的剩余下载时间?

0 个答案:

没有答案