基于Blob对象的Ajax进度条下载实现详解
本文详解如何利用XMLHttpRequest对象的responseType设置为blob,实现Ajax二进制文件下载。重点讲解进度监听、文件保存至本地、跨域处理及IE兼容方案,适用于需监控进度或后台处理的复杂下载场景。
普通浏览器下载与Ajax下载的区别
普通浏览器下载
在Web开发中,实现下载功能通常采用新开网页窗口或使用iframe嵌入的方式。具体实现较为简单:
<a target="_blank" href="download.zip" rel="external nofollow" >点击下载</a>
//或者
<iframe style="display:none" src="download.zip"></iframe>
当用户点击a标签弹出新页签,或打开iframe后,浏览器会接收到下载响应并开始下载附件。所谓附件下载,是指浏览器读取响应报文头后,生成下载提示框,用户确认后继续下载。文件本质上是数据流,浏览器会自动管理传输过程,包括生成进度条、停止/继续/取消按钮及显示已下载字节数等。这些均由浏览器自动完成,开发者无法直接控制整个过程。

Ajax下载
浏览器对下载的支持已能满足大多数需求,一般场景下探索其他方式意义不大。但在某些特定场景下,浏览器原生下载无法满足需求,例如需要监控下载进度、下载完成后触发特定事件、Web应用自动取消下载,或利用Worker创建后台下载任务等。针对上述情况,可采用基于Blob对象的Ajax下载方案。
Blob对象在Ajax下载中的应用
Ajax下载附件与上传类似,需浏览器支持Ajax 2.0标准。下载与普通Ajax请求的区别在于,下载通常涉及二进制文件而非文本或JSON对象,因此需要JavaScript提供封装二进制文件的类型,即Blob。为此,需将响应的responseType设置为“blob”:
var xhr =new XMLHttpRequest();
xhr.open(option.type ? option.type.toUpperCase() : 'GET', url, true);
xhr.responseType = 'blob';
要求XMLHttpRequest对象的responseType字段值为blob。那么,Blob对象究竟是什么?
Blob对象
MDN对其描述为:
Blob对象是包含只读原始数据的类文件对象。Blob中的数据不一定必须是JavaScript原生形式。File接口基于Blob,继承了Blob的功能,并扩展支持用户计算机上的本地文件。通过Blob对象,可以将二进制流封装为一个对象。
若熟悉HTML5中File相关的API,对Blob对象应不陌生。Blob能将字节流封装为文件,将XMLHttpRequest对象的responseType设为blob后,可将响应体作为Blob对象处理。
xhr.onload = function () {
//对于重定向的文件不予理会
if (this.status >= 200 && this.status < 300) {
var blob = new Blob([this.response], {type: this.response.type});
}
}
使用Ajax下载文件,并将文件保存为Blob对象,缓存在浏览器中。那么,如何让用户将文件保存到硬盘上呢?
Blob对象保存至本地硬盘的方法
将Blob对象保存在硬盘上
我们可以模仿浏览器下载行为,生成a标签或iframe,再生成URL,从而回归到浏览器下载模式,浏览器会自动生成保存附件的窗口。URL可通过URL.createObjectURL(blob)方法获取,该方法支持Blob和File对象,能生成虚拟URL供当前用户访问这些对象,包括下载。与直接从服务器下载不同,此下载在客户端内部进行,不涉及网络IO,因此几乎是瞬时的。生成URL后需释放,否则Blob资源不会被垃圾回收,可使用URL.revokeObjectURL释放该URL,从而释放Blob资源。对于IE浏览器,有一套独立的Blob处理策略,即通过navigator对象的msSaveOrOpenBlob和msSaveBlob两个方法实现。
//ie的下载
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, fileName);
} else {
//非ie的下载
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
}
进度条监控与下载取消功能
进度条和取消下载
接下来是进度条和下载取消功能。XMLHttpRequest对象提供了progress事件,但在普通Ajax请求中常被忽略,因为一般请求瞬时完成,无需进度条。然而,Ajax下载涉及文件传输,耗时较长,因此开发进度条很有必要。监听progress事件即可获取下载进度。
使用XMLHttpRequest对象的abort函数可取消下载。此外,load事件可监听下载完成,error事件可监听下载失败。总之,Ajax下载与普通Ajax请求的事件和方法完全一致。
性能优化与同源策略处理
性能优化和同源策略
Ajax下载与长连接类似,比普通请求占用更多带宽,尤其是大文件下载对带宽占用严重。因此,下载过程中可能阻塞其他Ajax请求,建议Ajax下载的资源与其他请求资源使用不同域名。但这会引发新的问题——同源策略问题。
同源策略是浏览器安全的基石,若无此策略,任何网站均可发起CSRF攻击。若下载资源的URL与当前页面URL不同源,将触发同源策略导致下载失败,因此需进行Ajax跨域处理。相比iframe和新页签下载(事实上iframe也有同源策略,要求iframe内页面与父页面不能互相访问内容,但下载功能不涉及此类访问,故iframe下载不受同源策略影响),Ajax下载本质上仍是Ajax,因此受浏览器同源策略影响。若下载非同源附件,需附件所在服务器支持CORS;若服务器需访问Cookie,还需将XMLHttpRequest对象的withCredentials设置为true。
同时,出于同源策略原因,不能使用Ajax形式下载第三方资源,因为通常下载服务不做CORS处理。毕竟iframe下载或新页签下载方式不受同源策略影响,无需CORS处理。这大大限制了Ajax下载的适用范围。
总结:
Ajax下载适用场景总结
最后再总结一下Ajax下载的使用场景:
1. 需监控下载进度的场景,例如发现用户下载进度过慢,主动提供其他解决方案。
2. 需下载完成后触发特定事件,例如弹出桌面提示Notification。
3. 需提供后台下载。例如在用户打开网页后将附件偷偷下载并缓存,待用户真正想下载时直接保存至本地。甚至可借助Worker创建后台线程,保证下载过程不影响页面正常渲染。
4. 需下载后不保存至硬盘,而是WebApp直接处理附件。例如pdf.js采用的就是Ajax下载方式。
最后奉上笔者的一个Ajax下载的demo:ajaxDownloadDemo_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
