Chrome扩展能否重命名正在下载的文件?附现有批量下载代码
问题
开发了一款Chrome扩展,通过向当前标签页注入JS模拟点击操作,批量下载PDF及EDI文件,目前已实现配置传递与注入执行的完整流程,但下载的文件名杂乱难以管理。曾尝试用外部Python脚本实时处理已下载文件,不够便捷且多进程运行对用户不友好,希望通过Chrome扩展实现下载时或下载前重命名文件。
解决方案
核心思路是利用Chrome扩展的downloadsAPI拦截下载请求,或直接通过API发起下载并指定自定义文件名,替代原有的模拟点击下载逻辑。
1. 配置扩展权限
修改manifest.json,添加必要权限以支持下载控制:
{ "manifest_version": 3, "permissions": ["downloads", "scripting", "storage", "tabs"], "host_permissions": ["<all_urls>"], // 替换为目标网站的具体域名更安全 "background": { "service_worker": "background.js" }, // 保留原有扩展配置(如popup、图标等) }
2. 后台脚本拦截并修改下载请求
新建background.js,用于监听下载事件并执行重命名:
// 存储待重命名的文件映射(URL -> 目标文件名) const pendingRenames = new Map(); // 监听下载创建事件,触发重命名 chrome.downloads.onCreated.addListener(downloadItem => { const targetFilename = pendingRenames.get(downloadItem.url); if (targetFilename) { chrome.downloads.update(downloadItem.id, { filename: targetFilename }); pendingRenames.delete(downloadItem.url); } }); // 接收注入脚本的重命名准备请求 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "prepareRename") { pendingRenames.set(request.url, request.filename); sendResponse({ success: true }); } });
3. 修改注入脚本(getPagesSource.js)的下载逻辑
不再模拟点击下载按钮,改为提取实际下载链接并通知后台准备重命名:
async function downloadFiles(document_root) { // 保留原有循环、筛选、弹窗打开等逻辑... // 替换原模拟点击EDI下载的代码 if (conf_edi) { // 提取EDI下载链接(根据页面实际结构调整选择器) const ediLink = document_root.querySelector("#uikit-root > div > div.modal-dialog.modal-xl > div > div.modal-header > div.modal-header-buttons > div.dropdown.btn-group.open > ul > li > a"); const ediUrl = ediLink.href; // 获取用于生成文件名的标识(如订单号、类型) const orderNumber = document_root.querySelector(`#root > div > div.ApplicationLayoutBody.has-footer > div > div > div:nth-child(4) > div:nth-child(1) > table > tbody > tr:nth-child(${i}) > td:nth-child(2)`).innerText; const targetEdiName = `[${span || "Normal"}] ${orderNumber}.edi`; // 通知后台准备重命名 await chrome.runtime.sendMessage({ action: "prepareRename", url: ediUrl, filename: targetEdiName }); // 发起下载 window.open(ediUrl, "_blank"); } // 替换原模拟点击PDF下载的代码 if (conf_pdf) { const pdfLink = document_root.querySelector("#uikit-root > div > div.modal-dialog.modal-xl > div > div.modal-header > div.modal-header-buttons > div.dropdown.btn-group:nth-child(2).open > ul > li > a"); const pdfUrl = pdfLink.href; const orderNumber = document_root.querySelector(`#root > div > div.ApplicationLayoutBody.has-footer > div > div > div:nth-child(4) > div:nth-child(1) > table > tbody > tr:nth-child(${i}) > td:nth-child(2)`).innerText; const targetPdfName = `[${span || "Normal"}] ${orderNumber}.pdf`; await chrome.runtime.sendMessage({ action: "prepareRename", url: pdfUrl, filename: targetPdfName }); window.open(pdfUrl, "_blank"); } // 保留原有弹窗关闭、计数更新等逻辑... }
4. 替代方案:直接用API发起下载
如果能直接获取文件内容或稳定下载链接,可跳过拦截,直接在后台发起下载:
// 在background.js中添加下载处理逻辑 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "downloadDirectly") { chrome.downloads.download({ url: request.url, filename: request.filename, saveAs: false }, downloadId => { sendResponse({ success: !chrome.runtime.lastError, error: chrome.runtime.lastError?.message }); }); return true; // 保持消息通道异步响应 } }); // 在注入脚本中调用 await chrome.runtime.sendMessage({ action: "downloadDirectly", url: fileUrl, filename: targetFilename });
关键注意事项
- 提取真实下载链接:需根据页面实际DOM结构调整选择器,若链接为动态生成,可监听页面的XHR/fetch请求获取真实地址。
- 文件名唯一性:生成文件名时建议添加时间戳或序号,避免文件覆盖。
- 权限限制:确保
host_permissions覆盖目标网站域名,避免跨域权限问题。
内容的提问来源于stack exchange,提问作者Komaromi Adrian
相关产品推荐
相关产品推荐

