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

使用WebClient.DownloadFile()时返回403错误的技术求助

解决WebClient下载图片返回403错误的问题

问题根源分析

  1. 静态Cookie失效:你手动添加的cf_chl_3是Cloudflare生成的临时验证Cookie,有效期极短,昨天能用今天失效完全是因为Cookie过期了,静态复制的Cookie无法长期复用。
  2. 请求头不匹配:你给GET请求添加了Content-Type、Content-Length这类POST请求专属的头,服务器会判定请求不合法。
  3. 缺少Referer验证:目标服务器可能会检查图片请求的来源页面,没有Referer头会触发反爬拦截。
  4. WebClient的局限性:WebClient是较老旧的API,会话管理和请求控制不如HttpClient灵活。

解决方案1:使用HttpClient(推荐)

HttpClient支持自动会话保持,能动态获取并维护Cookie,请求控制更精细。

初始化带会话的HttpClient

var handler = new HttpClientHandler
{
    CookieContainer = new CookieContainer(),
    UseCookies = true,
    // 自动处理压缩,匹配浏览器行为
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli
};

var httpClient = new HttpClient(handler)
{
    BaseAddress = new Uri("https://thebarchive.com/")
};

// 添加浏览器核心请求头,仅保留GET请求需要的
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
httpClient.DefaultRequestHeaders.Add("Accept", "image/avif,image/webp,*/*;q=0.8");
httpClient.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.5");
httpClient.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");

完整下载逻辑

// 先访问线程页面,获取会话Cookie(关键步骤)
var html = await httpClient.GetStringAsync(ThreadLink);
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(html);

var piclinks = htmlDocument.DocumentNode.Descendants("div")
    .Where(node => node.GetAttributeValue("class", "").Contains("thread_image_box"))
    .ToList();

foreach (var imagelink in piclinks)
{
    string link = imagelink.InnerHtml;
    string linkfull = link.Substring(link.IndexOf("t/") + 2, link.IndexOf("target=") - 2 - (link.IndexOf("t/") + 2));
    string downloadlink = $"https://thebarchive.com/b/full_image/{linkfull}";

    try
    {
        // 创建GET请求并添加Referer头
        var request = new HttpRequestMessage(HttpMethod.Get, downloadlink);
        request.Headers.Referrer = new Uri(ThreadLink);

        // 发送请求并保存文件
        using (var response = await httpClient.SendAsync(request))
        {
            response.EnsureSuccessStatusCode(); // 主动抛出非200状态码异常
            using (var stream = await response.Content.ReadAsStreamAsync())
            using (var fileStream = new FileStream(Path.Combine(folder, linkfull), FileMode.Create))
            {
                await stream.CopyToAsync(fileStream);
            }
        }
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"下载失败,状态码:{ex.StatusCode}");
        Console.WriteLine(ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("无法加载文件,可能是视频或其他错误");
        Console.WriteLine(ex.Message);
    }
}

解决方案2:修正WebClient的请求配置

如果坚持使用WebClient,需要移除无效请求头并动态获取Cookie:

var wc = new WebClient();
// 仅保留GET请求需要的头
wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
wc.Headers.Add("Accept", "image/avif,image/webp,*/*");
wc.Headers.Add("Accept-Encoding", "gzip, deflate, br");
wc.Headers.Add("Referer", ThreadLink); // 必须添加Referer

// 先访问线程页面,获取动态会话Cookie
wc.DownloadString(ThreadLink);

// 执行下载
try
{
    wc.DownloadFile(downloadlink, Path.Combine(folder, linkfull));
}
catch (Exception ex)
{
    Console.WriteLine("无法加载文件,可能是视频或其他错误");
    Console.WriteLine(ex);
}

核心注意事项

  • 绝对不要使用静态复制的Cloudflare Cookie,这类Cookie几分钟内就会过期,必须通过先访问目标页面的方式动态获取。
  • GET请求不要添加POST专属的请求头(Content-Type、Content-Length等),否则会触发服务器的非法请求拦截。
  • 必须添加Referer头,证明图片请求来自合法的页面来源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:33:24