纯前端下载首选 fetch + Blob 方案,但需后端支持 CORS;同源可直接用 download 属性;大文件应避免全量加载内存;Content-Disposition 响应头最省事但需后端配合。

链接加 download 属性就能触发下载?别急,先看浏览器支持情况
纯前端实现文件下载,最直接的方式是在 <a></a> 标签上加 download 属性,比如:
<a href="report.pdf" download="my-report.pdf">下载报告</a>但这个属性只对同源 URL 有效——如果
href 指向的是跨域资源(比如 CDN 上的 https://cdn.example.com/data.csv),Chrome、Edge 会忽略 download,直接在新标签页打开文件。Firefox 更严格,连同域的 blob URL 有时也不认。
用 fetch + Blob + URL.createObjectURL 绕过跨域限制
这是目前最可靠、兼容性较好的纯前端方案,核心逻辑是:拉取文件内容 → 构造成 Blob → 创建本地 blob URL → 触发下载。关键点在于:
-
fetch必须能拿到完整响应体(不能被 CORS 阻止),所以后端需返回Access-Control-Allow-Origin: *或明确允许你的域名 - 不要用
response.json()或response.text(),得用response.blob() - 创建的 blob URL 要在下载完成后手动
URL.revokeObjectURL,否则内存泄漏
简单示例:
async function downloadFile(url, filename) {
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const blob = await res.blob();
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl); // 别漏掉这句
} catch (err) {
console.error('下载失败:', err);
}
}
Content-Disposition 响应头比前端更省事,但得后端配合
如果你能控制服务端,这是最轻量的方案:只要响应头里带 Content-Disposition: attachment; filename="data.xlsx",浏览器收到就自动弹保存框,完全不用前端写逻辑。注意:
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
立即学习“前端免费学习笔记(深入)”;
- 这个头对所有请求都生效(包括直接在地址栏输入 URL),适合明确“只用于下载”的接口
- 如果同时要支持 API 返回 JSON 和文件下载,得拆成两个 endpoint,或者用 query 参数区分(如
/export?format=csv&download=1) - 某些代理或 CDN 可能过滤或覆盖该头,上线前务必实测
大文件下载时,别用 fetch 全部载入内存
几 MB 的文件用 fetch + blob 没问题,但遇到几百 MB 的日志或导出包,await res.blob() 会把整个文件塞进内存,可能卡死页面。这时候应该:
- 改用
<a download></a>直链(前提是同源或后端已配好Content-Disposition) - 服务端生成预签名 URL(如 S3 presigned URL),前端直接跳转或赋给
a.href,不经过 JS 处理 - 真要走前端流式处理,得用
ReadableStream+stream.pipeTo()写到WritableStream,但浏览器下载 API 不支持流式写入,最终还是得攒成 blob —— 所以大文件尽量避开纯前端方案
真正难的不是怎么写那几行代码,而是判断清楚:这个文件谁负责准备、是否跨域、有多大、用户点击后是否需要做权限校验或埋点——这些决定了你该选哪条路。

















