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

Chrome扩展中如何通过chrome.downloads API获取已下载文件?

解决Chrome扩展无法获取下载文件完整路径及内容的问题

核心限制与前提

Chrome出于安全限制,普通扩展不能直接读取本地文件系统,需通过downloads API配合正确权限实现,且Manifest V2和V3的实现方式有差异。

步骤1:配置Manifest权限

根据你的Manifest版本添加对应权限:

Manifest V3

{
  "manifest_version": 3,
  "name": "你的扩展名称",
  "version": "1.0",
  "permissions": ["downloads", "storage", "<all_urls>"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

Manifest V2

{
  "manifest_version": 2,
  "name": "你的扩展名称",
  "version": "1.0",
  "permissions": ["downloads", "<all_urls>"],
  "background": {
    "scripts": ["background.js"]
  }
}

步骤2:监听下载完成事件并获取完整路径

在background.js中监听下载状态变更,当下载完成时获取文件完整路径:

chrome.downloads.onChanged.addListener((delta) => {
  // 仅处理状态变为完成的下载任务
  if (delta.state && delta.state.current === 'complete') {
    chrome.downloads.search({ id: delta.id }, (items) => {
      if (items.length === 0) return;
      const downloadItem = items[0];
      // fullPath即为文件的完整本地路径
      const fullFilePath = downloadItem.fullPath;
      
      // 根据Manifest版本处理文件读取
      if (chrome.runtime.getManifest().manifest_version === 3) {
        // Manifest V3:将路径存入storage,交由Popup处理
        chrome.storage.local.set({ pendingUpload: fullFilePath }, () => {
          chrome.notifications.create({
            type: 'basic',
            iconUrl: 'icon.png',
            title: '下载完成',
            message: '文件已就绪,点击扩展图标上传'
          });
        });
      } else {
        // Manifest V2:直接在背景页读取并上传
        readAndUploadFile(fullFilePath);
      }
    });
  }
});

步骤3:读取文件并上传至服务器

Manifest V2 直接读取(背景页实现)

在background.js中添加文件读取与上传函数:

function readAndUploadFile(filePath) {
  // 处理不同系统的file://路径格式
  const fileUrl = process.platform === 'win32' 
    ? `file:///${filePath.replace(/\\/g, '/')}` 
    : `file://${filePath}`;

  fetch(fileUrl)
    .then(res => res.blob())
    .then(blob => {
      const formData = new FormData();
      // 提取文件名,避免路径问题
      const fileName = filePath.split(/[\\/]/).pop();
      formData.append('file', blob, fileName);

      // 发送至服务器
      return fetch('https://你的服务器地址/upload', {
        method: 'POST',
        body: formData
      });
    })
    .then(res => res.json())
    .then(data => console.log('上传成功:', data))
    .catch(err => console.error('操作失败:', err));
}

Manifest V3 借助Popup读取

  1. 创建popup.html:
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>body { width: 200px; padding: 10px; }</style>
</head>
<body>
  <div id="status">等待文件上传...</div>
  <script src="popup.js"></script>
</body>
</html>
  1. 在popup.js中实现读取与上传:
document.addEventListener('DOMContentLoaded', () => {
  const statusEl = document.getElementById('status');
  chrome.storage.local.get('pendingUpload', (data) => {
    if (!data.pendingUpload) return;
    
    const filePath = data.pendingUpload;
    statusEl.textContent = '正在上传文件...';
    
    const fileUrl = process.platform === 'win32' 
      ? `file:///${filePath.replace(/\\/g, '/')}` 
      : `file://${filePath}`;

    fetch(fileUrl)
      .then(res => res.blob())
      .then(blob => {
        const formData = new FormData();
        const fileName = filePath.split(/[\\/]/).pop();
        formData.append('file', blob, fileName);

        return fetch('https://你的服务器地址/upload', {
          method: 'POST',
          body: formData
        });
      })
      .then(res => res.json())
      .then(data => {
        statusEl.textContent = '上传成功!';
        chrome.storage.local.remove('pendingUpload');
        setTimeout(() => window.close(), 1500);
      })
      .catch(err => {
        statusEl.textContent = '上传失败,请重试';
        console.error('操作失败:', err);
      });
  });
});

注意事项

  • fullPath属性的格式随操作系统变化,需注意路径拼接的兼容性
  • Manifest V3的Service Worker因沙箱限制无法直接访问file://资源,必须借助Popup或其他可访问本地文件的页面
  • 确保用户未在Chrome隐私设置中禁用扩展对file://协议的访问权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:43:23