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

使用Playwright下载文件时如何获取下载进度的百分比?

Playwright C# 获取下载进度百分比解决方案

Playwright 官方原生API暂未直接提供下载进度的回调事件,你目前的写法直接调用await e.SaveAsAsync(path)只能等待下载完成,无法获取中间进度,可通过以下两种方案实现:


方案1:提取下载链接用HttpClient自主下载(最稳定)

思路:在Download事件中拿到下载地址,复用Playwright上下文的请求头、Cookie,用HttpClient发起下载,通过进度回调计算百分比
示例代码:

using System.Net.Http.Headers;
using (var playWright = await Playwright.CreateAsync()) 
{ 
    string DownloadDirectory = @"你的本地保存目录";
    BrowserTypeLaunchOptions browserLaunchOptions = new BrowserTypeLaunchOptions() { Headless = true};
    var browser = await playWright.Chromium.LaunchAsync(browserLaunchOptions);
    var browserContextOptions = new BrowserNewContextOptions() { AcceptDownloads = true };
    var context = await browser.NewContextAsync(browserContextOptions);
    var page = await context.NewPageAsync();

    page.Download += async (object sender, IDownload e) => 
    { 
        var downloadUrl = e.Url;
        var savePath = Path.Combine(DownloadDirectory, e.SuggestedFilename);
        
        // 复用Playwright上下文的Cookie,避免权限校验失败
        var cookies = await context.CookiesAsync(new List<string> { downloadUrl });
        using var httpClient = new HttpClient();
        foreach (var cookie in cookies)
        {
            httpClient.DefaultRequestHeaders.Add("Cookie", $"{cookie.Name}={cookie.Value}");
        }
        // 发起请求获取响应头
        using var response = await httpClient.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
        response.EnsureSuccessStatusCode();
        var totalBytes = response.Content.Headers.ContentLength ?? -1;
        var downloadedBytes = 0L;
        var buffer = new byte[8192];
        
        await using var contentStream = await response.Content.ReadAsStreamAsync();
        await using var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length, true);
        int bytesRead;
        while ((bytesRead = await contentStream.ReadAsync(buffer)) > 0)
        {
            await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead));
            downloadedBytes += bytesRead;
            if (totalBytes > 0)
            {
                var progress = (double)downloadedBytes / totalBytes * 100;
                // 此处可替换为你自己的进度处理逻辑
                Console.WriteLine($"下载进度:{progress:F2}%");
            }
        }
    }; 
    await page.GotoAsync("你的目标页面URL");
}

注意:如果下载链接是一次性的或者带动态签名,需要保证HttpClient请求在链接失效前发起。


方案2:监控本地文件大小变化计算进度

思路:在调用SaveAsAsync的同时,启动后台任务轮询已保存的文件大小,结合响应头返回的文件总大小计算进度
示例代码片段:

page.Download += async (object sender, IDownload e) => 
{ 
    var savePath = Path.Combine(DownloadDirectory, e.SuggestedFilename);
    // 先获取下载响应的总大小
    var response = await e.ResponseAsync();
    var totalBytes = response.Headers.TryGetValue("Content-Length", out var contentLength) 
        ? long.Parse(contentLength) 
        : -1;
    // 开后台任务轮询进度
    _ = Task.Run(async () =>
    {
        while (!e.FailureAsync().IsCompleted)
        {
            await Task.Delay(500);
            if (File.Exists(savePath))
            {
                var fileInfo = new FileInfo(savePath);
                var downloadedBytes = fileInfo.Length;
                if (totalBytes > 0)
                {
                    var progress = (double)downloadedBytes / totalBytes * 100;
                    Console.WriteLine($"下载进度:{progress:F2}%");
                }
            }
        }
    });
    // 等待下载保存完成
    await e.SaveAsAsync(savePath);
    Console.WriteLine("下载完成");
};

注意:这个方案依赖响应头返回正确的Content-Length,如果是分片下载或者服务端没有返回该字段,总大小获取会失败,进度计算将不准确。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:27:03