
本文介绍通过中间页面拦截 .exe 等可执行文件直接下载行为的方法,利用 html + javascript 构建可控的下载跳转页,结合 url 参数解析与用户确认机制,在下载前提供内容检查与安全决策能力。
本文介绍通过中间页面拦截 .exe 等可执行文件直接下载行为的方法,利用 html + javascript 构建可控的下载跳转页,结合 url 参数解析与用户确认机制,在下载前提供内容检查与安全决策能力。
在现代浏览器中,当用户访问以 .exe、.msi、.bat 等结尾的 URL(如 https://example.com/installer.exe)时,浏览器通常会绕过页面渲染,直接触发下载——这意味着常规的 <script></script> 或 Web 扩展的 content_scripts 无法在下载开始前介入,导致无法进行安全校验、MIME 类型检查或用户确认。
根本原因:浏览器对已知二进制/可执行资源采用“直接下载”策略,不触发 DOMContentLoaded 或 load 事件,因此前端脚本无执行时机;同时,Manifest V3 扩展的 webRequest API 也不允许重写或阻断最终响应体(仅能重定向或取消请求,且需 host_permissions 和敏感权限声明)。
✅ 推荐方案:引入轻量级中间跳转页(推荐 download.html)
该方案无需后端,纯前端实现,兼顾兼容性与可控性:
-
将原始
.exe链接替换为跳转页链接
例如,把<a href="https://example.com/app.exe">下载</a>改为:<a href="download.html?url=https%3A%2F%2Fexample.com%2Fapp.exe">下载(安全检查中...)</a>
-
创建
download.html页面(含安全确认逻辑)<!DOCTYPE html> <html> <head><title>安全下载确认</title></head> <body style="font-family: -apple-system, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto;"> <h2>⚠️ 检测到可执行文件</h2> <p><strong>文件来源:</strong><span id="fileUrl"></span></p> <p>此文件可能具有系统权限,请确认其可信性后再继续。</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill8291" title="page-agent 浏览器控制(CDP)"><img src="https://img.php.cn/upload/skill/000/000/081/179196125775037.jpg" alt="page-agent 浏览器控制(CDP)" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill8291" title="page-agent 浏览器控制(CDP)">page-agent 浏览器控制(CDP)</a> <p>使用 page-agent CLI(CDP)控制浏览器;CLI只能通过 GitHub Release 的 .tgz 安装,npm 官方包暂未发布。</p> </div> <a href="/xiazai/skill8291" title="page-agent 浏览器控制(CDP)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <button onclick="startDownload()" style="padding: 0.5rem 1rem; background: #007bff; color: white; border: none; border-radius: 4px;">✅ 我已确认,开始下载</button> <button onclick="window.history.back()" style="margin-left: 0.5rem; padding: 0.5rem 1rem; background: #6c757d; color: white; border: none; border-radius: 4px;">◀ 返回</button> <script> // 解析 URL 参数(兼容 IE11+) function getQueryParam(param) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(param); } const exeUrl = decodeURIComponent(getQueryParam('url') || ''); document.getElementById('fileUrl').textContent = exeUrl; function startDownload() { if (!exeUrl || !exeUrl.match(/^https?:\/\//)) { alert('无效的下载地址'); return; } // ✅ 关键:使用 window.open 触发下载(避免被弹窗拦截需用户交互触发) window.open(exeUrl, '_blank'); } </script> </body> </html>
? 为什么用 window.open() 而非 fetch + Blob + a.download?
-
fetch无法跨域读取二进制响应头(如Content-Type),且大文件易内存溢出; -
window.open(url)复用浏览器原生下载逻辑,保留断点续传、进度提示等特性,且不触发 CORS 限制(因是导航而非资源获取); - 只要
window.open()在用户点击等同步事件中调用,现代浏览器不会拦截。
? 进阶建议(Web 扩展增强)
若需全局拦截所有 .exe 链接,可在 Manifest V3 扩展中注入 content script,重写页面内链接:
// content.js
document.addEventListener('click', (e) => {
const link = e.target.closest('a[href$=".exe"], a[href$=".msi"]');
if (link && link.href) {
e.preventDefault();
const encodedUrl = encodeURIComponent(link.href);
window.location.href = `download.html?url=${encodedUrl}`;
}
});⚠️ 注意:需在 manifest.json 中声明 "content_scripts" 和匹配权限,并确保 download.html 位于扩展包内(可通过 chrome.runtime.getURL('download.html') 获取路径)。
? 重要提醒
- 此方案不替代杀毒扫描或签名验证,仅提供用户知情与确认环节;
- 对于企业环境,建议配合 HTTP 响应头强化防护(如
Content-Disposition: attachment; filename="safe.exe"+X-Content-Type-Options: nosniff); - 浏览器未来可能收紧
window.open的下载行为(如 Chrome 125+ 对无用户手势的open()加强限制),请始终确保调用链源于明确用户操作(如click)。
通过这一简洁而鲁棒的设计,你能在零后端依赖的前提下,为用户提供关键的安全缓冲层——让每一次 .exe 下载,都始于一次清醒的选择。

















