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

使用CDP拦截请求时,如何直接返回二进制数据实现用户下载?

解决CDP拦截请求并触发直接下载的问题

虽然Fetch.fulfillRequest确实只接受base64编码的body,但这并不影响实现直接下载的需求——只需将二进制数据转成base64,再配合正确的响应头配置,就能让浏览器自动触发下载行为。

核心思路

  1. 二进制转base64:这是CDP的强制要求,所有返回的body必须是base64格式,可通过语言自带的工具函数完成转换(比如Node.js的Buffer.toString('base64'))。
  2. 配置响应头触发下载:关键设置Content-Disposition为attachment; filename="文件名.后缀",同时匹配文件对应的Content-Type,让浏览器识别这是需要下载的文件而非可渲染内容。

代码示例(Puppeteer场景)

const puppeteer = require('puppeteer');
const fs = require('fs');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // 读取本地二进制文件作为待返回的下载内容
  const fileBuffer = fs.readFileSync('./sample.zip');
  const base64Body = fileBuffer.toString('base64');

  // 开启请求拦截
  await page.setRequestInterception(true);
  page.on('request', (req) => {
    // 拦截目标下载请求(这里以URL包含/download为例)
    if (req.url().includes('/download')) {
      req.respond({
        status: 200,
        headers: {
          'Content-Type': 'application/zip', // 匹配文件MIME类型
          'Content-Disposition': 'attachment; filename="my-download.zip"' // 触发下载并指定文件名
        },
        body: base64Body
      });
    } else {
      req.continue();
    }
  });

  await page.goto('https://your-test-site.com');
  // 触发页面上的下载操作(比如点击下载按钮)
  await page.click('#download-btn');

  // 等待下载完成(根据实际情况调整时长)
  await new Promise(resolve => setTimeout(resolve, 3000));

  await browser.close();
})();

代码示例(纯CDP场景,使用chrome-remote-interface)

const CDP = require('chrome-remote-interface');
const fs = require('fs');

(async () => {
  const client = await CDP();
  const { Fetch, Page } = client;

  // 开启Fetch拦截,匹配目标请求URL
  await Fetch.enable({ patterns: [{ urlPattern: '*download*' }] });
  await Page.enable();

  const fileBuffer = fs.readFileSync('./sample.pdf');
  const base64Body = fileBuffer.toString('base64');

  // 处理拦截到的请求
  Fetch.requestPaused(async (event) => {
    await Fetch.fulfillRequest({
      requestId: event.requestId,
      responseCode: 200,
      // CDP的响应头需用数组形式的键值对
      responseHeaders: [
        { name: 'Content-Type', value: 'application/pdf' },
        { name: 'Content-Disposition', value: 'attachment; filename="document.pdf"' }
      ],
      body: base64Body
    });
  });

  await Page.navigate({ url: 'https://your-test-site.com' });
  await new Promise(resolve => setTimeout(resolve, 3000));

  await client.close();
})();

注意事项

  • 大文件转base64会增加约33%的体积,若处理超大文件,需评估性能影响;
  • Content-Type必须与文件格式匹配,否则可能出现下载后无法打开的问题;
  • 不同CDP封装库的响应头格式可能不同(比如Puppeteer用对象,原生CDP用数组),需注意对应格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:41:07