C# 制作一个httpclient静态下载程序

C# 制作一个httpclient静态下载程序,c#,httpclient,C#,Httpclient,我真的需要帮助。有人能帮我把这些代码设为静态的吗? 我在这里的某个地方找到了这个,我添加了一些代码。 但我注意到下载过程很慢,因为没有将httpclient作为单个实例使用 我想将其设置为静态,这样我就可以将httpclient和handler设置为所有请求的单个实例 我曾尝试将其设置为静态,但失败了,因为我无法从主gui窗体触发进度百分比和总字节数 下面是下载程序的完整源代码 class Downloader : IDisposable { private const

我真的需要帮助。有人能帮我把这些代码设为静态的吗? 我在这里的某个地方找到了这个,我添加了一些代码。 但我注意到下载过程很慢,因为没有将httpclient作为单个实例使用

我想将其设置为静态,这样我就可以将httpclient和handler设置为所有请求的单个实例

我曾尝试将其设置为静态,但失败了,因为我无法从主gui窗体触发进度百分比和总字节数

下面是下载程序的完整源代码

class Downloader : IDisposable
    {
        private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36";
        private string DownloadUrl { get; set; }
        private string OutputFilePath { get; set; }

        private HttpClientHandler handler;
        private HttpClient client;

        public delegate void ProgressChangedHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage);
        public delegate void ProgressChangedHandler2(double? progressPercentage);
        public event ProgressChangedHandler ProgressChanged; //for label progress
        public Downloader(string downloadUrl, string outputFilePath)
        {
            DownloadUrl = downloadUrl;
            OutputFilePath = outputFilePath;
        }

        public async Task StartDownload(CancellationToken token)
        {
            handler = new HttpClientHandler()
            {
                Proxy = null,
                UseProxy = false,
                UseCookies = false,
                //SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls,
                //ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
            };
            client = new HttpClient(handler);

            Uri uri = new Uri(DownloadUrl, UriKind.Absolute);

            SetConnection(uri);
            using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
            {
                request.RequestUri = uri;
                request.Headers.UserAgent.ParseAdd(UserAgent);

                using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token))
                {
                    await DownloadFileFromHttpResponseMessage(response, token);
                }
            }
        }
        private async Task DownloadFileFromHttpResponseMessage(HttpResponseMessage response, CancellationToken token)
        {
            response.EnsureSuccessStatusCode();

            using (var contentStream = await response.Content.ReadAsStreamAsync())
            {
                long? totalBytes = response.Content.Headers.ContentLength;
                long totalBytesRead = 0L;
                long readCount = 0L;
                byte[] buffer = new byte[4096];
                bool isMoreToRead = true;

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

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

                        totalBytesRead += bytesRead;
                        readCount += 1;

                        if (readCount % 10 == 0)
                        {
                            TriggerProgressChanged(totalBytes, totalBytesRead);
                        }
                    }
                    while (isMoreToRead);
                }
                TriggerProgressChanged(totalBytes, totalBytesRead);
            }
        }
        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);
        }
        private void SetConnection(Uri uri)
        {
            var sp = ServicePointManager.FindServicePoint(uri);
            sp.ConnectionLimit = 20; //default 2 //The number of connections per end point.
            sp.UseNagleAlgorithm = false; //Nagle’s algorithm is a means of improving the efficiency of TCP/IP networks by reducing the number of packets that need to be sent over the network
            sp.Expect100Continue = false; //save bandwidth before sending huge object for post and put request to ensure remote end point is up and running.
            sp.ConnectionLeaseTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;//60 * 1000; // 1 minute
        }
        public void Dispose()
        {
            client?.Dispose();
        }
    }
这是我的gui中的代码

using (var client = new Downloader(url, outputFilePath))
            {

                client.ProgressChanged += (totalFileSize, totalBytesDownloaded, progressPercentage) =>
                {
                    sw.Start();

                    if (tryAbort) { PauseOrResumeProcess(); }

                    PB.Value = Convert.ToInt32(progressPercentage);
                    lvi.SubItems[2].Text = ($"{progressPercentage}%");
                    lvi.SubItems[3].Text = ($"{ Utils.FormatFileSize(totalBytesDownloaded)} of { Utils.FormatFileSize(totalFileSize.Value)}");
                };

                await client.StartDownload(ct);
            }

最好将您的HttpClient添加为应用程序的作用域,这意味着每个应用程序只有一个HTTP客户端实例

只需添加
services.addScope()
到您的
配置服务(IServiceCollection服务)
启动类,并在那里进行配置。然后:

public Downloader(string downloadUrl, string outputFilePath, HttpClient client)
{
    DownloadUrl = downloadUrl;
    OutputFilePath = outputFilePath;
    this.client = client;
}
更新: 好吧,这是我尝试过的,它成功了。 我刚刚删除了IDisposable,只将客户端和处理程序更改为静态,获得了最大下载速度

 private static readonly HttpClientHandler handler = new HttpClientHandler()
    {
        Proxy = null,
        UseProxy = false
    };
    private static readonly HttpClient client = new HttpClient(handler);

啊。什么意思?那么这个代码可以吗?我只想删除IDisposable?使
客户端成为
静态成员,不要使用
Dispose()
。因为HttpClient是要被重用的,所以它不应该被处理等等,如果它能工作,我会试试的。多谢各位much@PanagiotisKanavos哇,成功了。我只是将客户端和处理程序更改为静态,并获得了高速下载。我想我必须让所有的代码都是静态的,这就是我失败的原因。您可以使单个属性自身处于静态状态。Ahm。我还不熟悉addscoped。但我会在google=D上查看,你能告诉我在哪里可以输入吗?是的,它是为.net应用程序提供的,你在使用什么吗?=)好的)C#是一种可用于.Net平台应用程序的语言=D那么您在桌面、Web或某些类库上使用的是哪种类型的应用程序?)啊,对不起,桌面:)