You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何结合Chrome扩展API获取下载请求的完整HTTP信息?

正确关联chrome.webRequestchrome.downloads事件的解决方案

你遇到的核心问题是全局变量会被频繁触发的webRequest事件覆盖,导致onDeterminingFilename拿到的请求详情大概率不是当前下载对应的那个。要解决这个问题,我们需要用**请求唯一标识(requestId)**来建立两个事件的关联,而不是用全局变量。

思路解析

每个webRequest事件都会生成唯一的requestId,而触发下载的请求会被记录在downloadItemrequestChain属性中。我们可以用一个Map来存储requestId到请求详情的映射,这样每个请求的详情都能独立存储,不会被覆盖。在下载事件触发时,通过requestChain找到对应的requestId,再从Map中取出匹配的请求详情即可。

完整代码示例

// 用Map存储requestId到请求详情的映射,替代全局变量
const requestDetailsMap = new Map();

// 监听webRequest的请求头发送前事件,存储请求详情
chrome.webRequest.onBeforeSendHeaders.addListener(
  (details) => {
    // 将当前请求详情存入Map,键为唯一的requestId
    requestDetailsMap.set(details.requestId, details);

    // 超时自动清理:5分钟后移除过期的请求详情,避免内存泄漏
    setTimeout(() => {
      requestDetailsMap.delete(details.requestId);
    }, 5 * 60 * 1000);

    return { requestHeaders: details.requestHeaders };
  },
  { urls: ["<all_urls>"] },
  ["blocking", "requestHeaders", "extraHeaders"]
);

// 监听下载文件名确定事件,关联对应的请求详情
chrome.downloads.onDeterminingFilename.addListener(async (downloadItem, suggest) => {
  let targetRequestId = null;

  // 从downloadItem的requestChain中提取触发下载的requestId
  if (downloadItem.requestChain && downloadItem.requestChain.length > 0) {
    // 通常第一个request就是触发下载的源头请求
    targetRequestId = downloadItem.requestChain[0].requestId;
  }

  if (targetRequestId && requestDetailsMap.has(targetRequestId)) {
    // 获取当前下载对应的完整请求详情
    const requestDetails = requestDetailsMap.get(targetRequestId);
    
    // 在这里处理你的业务逻辑,比如获取请求方法、请求头等
    console.log("请求方法:", requestDetails.method);
    console.log("请求头:", requestDetails.requestHeaders);

    // 处理完成后删除Map中的条目,释放内存
    requestDetailsMap.delete(targetRequestId);
  } else {
    // 容错处理:如果找不到对应请求详情(比如本地文件下载)
    console.log("未找到当前下载对应的请求详情");
  }

  // 必须调用suggest来确定文件名,否则下载会被阻塞
  suggest({ filename: downloadItem.filename });
});

关键注意事项

  • 权限配置:确保你的扩展manifest.json中声明了webRequestwebRequestBlockingdownloads权限,以及对应的主机权限(比如<all_urls>)。
  • 容错处理requestChain可能为空(比如用户直接下载本地文件、浏览器生成的下载),这时候要做好无请求详情的兼容逻辑。
  • 内存管理:通过超时清理机制避免Map积累大量过期数据,防止扩展内存占用过高。

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

火山引擎 最新活动