Tampermonkey脚本中Blob下载自动存为.bin文件而非指定.webm文件的问题求助
Tampermonkey脚本中Blob下载自动存为.bin文件而非指定.webm文件的问题求助
嘿,我碰到过几乎一模一样的问题!折腾了好半天终于搞明白,核心问题大概率是Tampermonkey的沙箱隔离机制在搞鬼,和你直接用a标签或者GM_download的方式关系不大。先给你几个亲测有效的解决方案,再唠唠背后的原因:
方案1:把下载逻辑注入到页面主上下文(最靠谱,和你提到的网站做法对齐)
Tampermonkey的脚本默认跑在隔离的沙箱里,你在沙箱里创建的a标签,浏览器可能会忽略它的download属性——毕竟沙箱里的元素和页面主环境的元素不是一个“世界”的。而你说的那个音频编辑器网站,代码是直接跑在页面主上下文,完全不受沙箱限制,所以download属性能正常生效。
解决办法就是把下载代码“搬”到页面主环境执行,示例代码如下:
const audioBlob = new Blob(audioChunks, { type: 'audio/webm;codecs=opus' }); // 创建脚本标签,把下载逻辑注入到页面主环境 const injectScript = document.createElement('script'); injectScript.textContent = ` function handleAudioDownload(blob, filename) { const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; // 必须把链接加到DOM树再点击,部分浏览器有这个要求 document.body.appendChild(link); link.click(); // 清理资源,避免内存泄漏 document.body.removeChild(link); URL.revokeObjectURL(url); } `; document.head.appendChild(injectScript); document.head.removeChild(injectScript); // 注入后立即删除,不污染DOM // 调用主环境里的下载函数(用unsafeWindow访问页面主上下文) unsafeWindow.handleAudioDownload(audioBlob, 'recording.webm');
这个方法完全模拟了正常页面的下载逻辑,和你提到的网站做法一致,基本不会出问题。
方案2:正确使用GM_download(适合不想折腾上下文的情况)
你说你试过GM_download,但大概率是用法不对——GM_download早期版本不支持直接传Blob URL,必须把Blob转成Base64的Data URL,还要记得加对权限。
步骤如下:
- 先在脚本开头的元数据里添加必要权限:
// @grant GM_download
- 用FileReader把Blob转成Data URL,再调用GM_download:
const audioBlob = new Blob(audioChunks, { type: 'audio/webm;codecs=opus' }); const reader = new FileReader(); reader.onload = function(e) { GM_download({ url: e.target.result, // 这里是Base64格式的Data URL name: 'recording.webm', headers: { 'Content-Type': 'audio/webm;codecs=opus' }, saveAs: true // 强制弹出保存对话框,确保文件名生效 }); }; reader.readAsDataURL(audioBlob);
为什么你的原代码不生效?
再给你捋清楚根因:
- 沙箱隔离限制:Tampermonkey的沙箱和页面主环境是完全隔离的,你在沙箱里创建的a标签,浏览器的下载管理器可能会把它当成“沙箱内部请求”,忽略
download属性, fallback到Blob的默认处理逻辑(生成随机.bin文件名)。 - GM_download的坑:直接传Blob URL给GM_download时,油猴的沙箱可能会拦截请求,导致浏览器无法识别Blob的MIME类型和预设文件名。
- 你提到的音频编辑器网站,代码直接跑在页面主上下文,没有沙箱的限制,所以
download属性能被浏览器正常解析,弹出正确的保存对话框。
额外排查小技巧
如果还是不行,可以试试这些:
- 检查Tampermonkey的设置,有没有开启“拦截下载”或者“修改下载行为”的选项,关掉它。
- 确保脚本的
@run-at设置成document-end或者document-idle,避免DOM未加载完成就执行下载逻辑。 - 试试把Blob转成File对象再处理:
const audioFile = new File([audioBlob], 'recording.webm', { type: 'audio/webm;codecs=opus' });,某些浏览器对File对象的支持比Blob更友好。
备注:内容来源于stack exchange,提问作者Ex-Opera
相关产品推荐
相关产品推荐

