JavaScript文件下载核心是用Blob封装数据并配合标签的download属性触发强制下载,关键在于正确构造符合目标格式的Blob对象并及时释放URL资源。

JavaScript 实现文件下载,核心是用 Blob 封装数据,再通过 URL.createObjectURL() 创建临时 URL,最后用 标签触发下载。关键不在“能不能”,而在“怎么构造 Blob 才符合目标文件格式”。
Blob 对象怎么创建?
Blob 是浏览器原生对象,表示不可变的、原始二进制数据。它不等于字符串或数组,但可以由多种类型的数据构造:
- 传入一个数组(元素可以是
String、ArrayBuffer、Uint8Array、Blob等) - 可选第二个参数为配置对象:
{ type: 'mime/type' },比如'text/plain'或'application/json'
常见写法示例:
// 下载纯文本
const blob = new Blob(['Hello, world!'], { type: 'text/plain' });
// 下载 JSON 字符串(注意:要先转成字符串)
const data = { name: 'Alice', score: 95 };
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
// 下载二进制内容(如从 fetch 获取的 ArrayBuffer)
fetch('/api/report.pdf')
.then(res => res.arrayBuffer())
.then(buf => {
const blob = new Blob([buf], { type: 'application/pdf' });
// 后续下载逻辑...
});
如何触发真实下载(而非打开)?
仅靠 window.open(url) 或直接跳转,浏览器可能在新标签页打开文本/图片/PDF,而不是下载。必须用 标签 + download 属性:
立即学习“Java免费学习笔记(深入)”;
云模块_YunMOK网站管理系统采用PHP+MYSQL为编程语言,搭载自主研发的模块化引擎驱动技术,实现可视化拖拽无技术创建并管理网站!如你所想,无限可能,支持创建任何网站:企业、商城、O2O、门户、论坛、人才等一块儿搞定!永久免费授权,包括商业用途; 默认内置三套免费模板。PC网站+手机网站+适配微信+文章管理+产品管理+SEO优化+组件扩展+NEW Login界面.....目测已经遥遥领先..
-
download属性存在时,浏览器强制下载(即使 MIME 类型支持预览) -
download的值就是保存的文件名(可省略后缀,但建议带上,如'report.json') - 生成的 URL 需通过
URL.createObjectURL(blob)创建,它是临时的、单次有效的引用
完整下载函数示例:
function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 用完及时释放,避免内存泄漏
}
常见问题与注意事项
实际使用中容易踩坑的地方:
-
中文文件名乱码:部分浏览器(尤其旧版 Safari)对
download中含中文名支持差。稳妥做法是用英文名,或服务端生成文件时处理编码 -
Blob 内容为空或格式错误:检查传入
Blob构造函数的数组元素是否为有效数据(例如别误传undefined或空对象) -
大文件卡顿:前端生成大 Blob(如百 MB 日志)会阻塞主线程。可考虑流式下载(
ReadableStream+response.body),或交由后端提供直链 -
移动端兼容性:iOS Safari 对
download属性基本不支持,此时可提示用户“长按链接保存”,或改用后端生成临时下载地址
替代方案:直接下载远程文件(无需 Blob)
如果只是想下载一个已知 URL 的文件(比如 CDN 上的 PDF),不需要前端构造数据,更简单:
function downloadFromUrl(url, filename) {
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
}
注意:该方式受跨域限制 —— 若 url 跨域且响应头不含 Access-Control-Allow-Origin,浏览器会拒绝发起请求(此时仍需走后端代理或 Blob 中转)。









