如何准确更新Firefox Downloads API中DownloadItem的exists属性?
如何准确检查下载文件是否仍存在于磁盘?
问题背景
MDN文档提到“要检查文件是否存在,调用downloads.search()方法并过滤目标文件”,但实际在Firefox中调用downloads.search({exists: true})时,仍会返回已从磁盘删除的文件——即使文件已被手动删除,对应的DownloadItem的exists属性依然为true。
另外,downloads.show()始终返回true(哪怕文件不存在),而downloads.open()会在文件存在时直接打开文件,不符合需求:希望文件存在时打开其所在文件夹,不存在时向用户发出通知。
已知打开浏览器内置下载弹窗或页面会自动更新DownloadItem状态,但希望通过编程实现这一状态更新,目前尝试的downloads.search()请求无法实现。
问题重现步骤
- 使用Firefox浏览器;
- 安装具备
downloadsAPI权限的测试扩展:- 下载并解压扩展文件;
- 打开Firefox的
about:debugging#/runtime/this-firefox页面; - 展开「临时扩展」面板,点击「加载临时附加组件」,选择解压后的
manifest.json文件完成加载; - 点击扩展面板上的「检查」,打开后台页面开发者工具;
- 下载任意文件;
- 通过操作系统手动删除该文件(请勿打开浏览器内置下载弹窗或页面,否则会自动更新
DownloadItem状态); - 在后台页面开发者工具控制台执行:
await browser.downloads.search({exists: true}); - 结果:刚被删除的文件对应的
DownloadItem仍在返回数组中,且exists属性仍为true。
解决方案
方法1:利用downloads.show()触发状态更新
虽然downloads.show()返回值不可靠,但调用它会强制浏览器重新检查文件存在性,从而更新DownloadItem的exists属性。可以先调用该方法,再查询最新状态:
async function checkFileExists(downloadId) { // 触发浏览器重新校验文件状态 await browser.downloads.show(downloadId); // 获取该下载项的最新状态 const [item] = await browser.downloads.search({id: downloadId}); return item?.exists; }
方法2:直接验证文件路径
如果不想依赖downloads API的状态同步,可通过文件路径直接验证存在性(需在manifest.json中添加对应文件系统权限):
async function checkFileExistsDirectly(filePath) { try { // Firefox支持通过Fetch访问本地文件 await fetch(`file://${filePath}`); return true; } catch (e) { return false; } } // 使用示例 const [item] = await browser.downloads.search({id: targetDownloadId}); const exists = await checkFileExistsDirectly(item.path);
实现目标逻辑
结合上述方法,完成“打开文件夹/通知用户”的需求:
async function handleDownloadItem(downloadId) { const exists = await checkFileExists(downloadId); if (exists) { // 文件存在,打开所在文件夹 await browser.downloads.show(downloadId); } else { // 文件不存在,发送通知 await browser.notifications.create({ type: 'basic', iconUrl: 'icons/notification-icon.png', // 替换为你的扩展图标路径 title: '文件不存在', message: '该下载文件已从磁盘删除' }); } }
内容的提问来源于stack exchange,提问作者Queza
相关产品推荐
相关产品推荐

