You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加快从远程URL获取文件大小的速度?

如何加速批量远程文件大小检测(无需下载)

你的思路其实很对——用HEAD请求获取Content-Length而不下载整个文件,这已经是最省带宽的方式了。现在慢的核心问题是串行处理400多个请求,每个请求都要等前一个完成,总耗时是所有请求耗时的总和。下面给你几个具体的优化方案,直接改代码就能大幅提速:

核心优化点

  • 并行请求+并发控制:同时发起多个HEAD请求,但要限制并发数,避免触发目标服务器的限流/反爬机制
  • 替换HttpWebRequest为HttpClient:HttpWebRequest是旧API,HttpClient更高效且支持复用,能减少连接建立的开销
  • 添加错误处理:应对链接失效、服务器不支持HEAD请求等异常情况

修改后的完整代码

1. 复用的HttpClient实例(关键!)

首先创建一个全局复用的HttpClient,不要每次请求都创建新实例:

// 推荐放在类的静态字段里,整个应用生命周期复用
private static readonly HttpClient _httpClient = new HttpClient(new HttpClientHandler())
{
    DefaultRequestHeaders =
    {
        { "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" }
    }
};

2. 带并发控制的文件大小获取方法

/// <summary>
/// 批量获取远程文件大小,带并发控制
/// </summary>
/// <param name="urls">待检测的URL列表</param>
/// <param name="maxConcurrentRequests">最大并发数,推荐10-20,根据目标服务器调整</param>
/// <returns>总文件大小(字节)</returns>
public static async Task<long> GetTotalFileSizeAsync(IEnumerable<string> urls, int maxConcurrentRequests = 15)
{
    var semaphore = new SemaphoreSlim(maxConcurrentRequests);
    var tasks = new List<Task<long>>();

    foreach (var urlStr in urls)
    {
        // 跳过空行
        if (string.IsNullOrWhiteSpace(urlStr)) continue;

        tasks.Add(Task.Run(async () =>
        {
            await semaphore.WaitAsync();
            try
            {
                if (!Uri.TryCreate(urlStr, UriKind.Absolute, out var uri))
                {
                    Console.WriteLine($"无效URL:{urlStr}");
                    return 0;
                }

                using var request = new HttpRequestMessage(HttpMethod.Head, uri);
                using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
                
                // 处理服务器不支持HEAD请求的情况(比如返回405),可以降级为GET但只取 headers
                if ((int)response.StatusCode == 405)
                {
                    request.Method = HttpMethod.Get;
                    using var getResponse = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
                    getResponse.EnsureSuccessStatusCode();
                    return getResponse.Content.Headers.ContentLength ?? 0;
                }

                response.EnsureSuccessStatusCode();
                return response.Content.Headers.ContentLength ?? 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"请求失败 {urlStr}:{ex.Message}");
                return 0;
            }
            finally
            {
                semaphore.Release();
            }
        }));
    }

    // 等待所有任务完成,然后求和
    var sizes = await Task.WhenAll(tasks);
    return sizes.Sum();
}

3. 保留你的格式化方法(无需修改)

public static string FormatFileSize(long bytes)
{
    var unit = 1024;
    if (bytes < unit)
    {
        return $"{bytes} B";
    }
    var exp = (int)(Math.Log(bytes) / Math.Log(unit));
    return $"{bytes / Math.Pow(unit, exp):F2} " + $"{("KMGTPE")[exp - 1]}B";
}

4. 调用示例(异步化,避免阻塞UI)

// 注意:UI线程中要使用await,不要用Task.Run阻塞
private async void btnCheckSizes_Click(object sender, EventArgs e)
{
    Cursor = Cursors.WaitCursor;
    try
    {
        var urls = tbResult.Lines.Where(line => !string.IsNullOrWhiteSpace(line)).ToList();
        var totalBytes = await GetTotalFileSizeAsync(urls);
        var formattedSize = FormatFileSize(totalBytes);
        Console.WriteLine($"总文件大小:{formattedSize}");
        // 也可以显示在UI控件里,比如:
        // lblTotalSize.Text = $"总大小:{formattedSize}";
    }
    catch (Exception ex)
    {
        MessageBox.Show($"检测失败:{ex.Message}");
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}

优化效果说明

  • 原来的串行处理:假设每个请求耗时1秒,400个请求需要400秒(约6.7分钟)
  • 优化后的并行处理:用15个并发,总耗时大概是400/15 ≈ 27秒(实际取决于网络和服务器响应速度),提速非常明显

注意事项

  • 调整maxConcurrentRequests的值:如果目标服务器限制严格,就调小(比如5-10);如果服务器允许,就调大(比如20-30)
  • 错误处理很重要:有些服务器可能禁止HEAD请求,或者返回的Content-Length为空,代码里已经做了降级处理和异常捕获
  • 不要频繁创建HttpClient:复用实例能减少TCP连接建立的开销,这是性能提升的关键之一

内容的提问来源于stack exchange,提问作者zackmark15

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:12:35