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读取
- 创建
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>
- 在
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
相关产品推荐
相关产品推荐

