JavaScript:如何在文件下载前后正确触发函数?
解决文件下载时fadeIn/fadeOut时机不对的问题
这个问题的核心在于document.location = "/Employee/Data?Type=CSV"是异步触发下载的——浏览器会立即发送请求,但不会等待文件下载完成就继续执行后面的fn_fadeOutWaiting()。小文件下载速度快,刚好能跟上代码执行节奏,大文件就会出现等待动画提前消失的情况。
这里有几个靠谱的解决方案,按推荐程度排序:
方案1:使用Fetch API + Blob 创建下载链接
这种方法可以直接监听文件下载完成的事件,完美控制fade的时机:
// 先显示等待动画 fn_fadeInWaiting(); // 用Fetch请求文件 fetch("/Employee/Data?Type=CSV") .then(response => { // 确保请求成功 if (!response.ok) throw new Error("下载请求失败"); return response.blob(); }) .then(blob => { // 创建下载链接 const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; // 设置文件名(如果后端返回了Content-Disposition,也可以从header里解析) a.download = 'employee_data.csv'; document.body.appendChild(a); a.click(); // 清理资源 URL.revokeObjectURL(url); document.body.removeChild(a); // 下载完成,隐藏等待动画 fn_fadeOutWaiting(); }) .catch(error => { console.error("下载出错:", error); // 出错也要隐藏动画,避免一直显示 fn_fadeOutWaiting(); });
方案2:使用XMLHttpRequest(兼容旧浏览器)
如果需要兼容不支持Fetch的旧浏览器,可以用XHR:
fn_fadeInWaiting(); const xhr = new XMLHttpRequest(); xhr.open('GET', "/Employee/Data?Type=CSV", true); xhr.responseType = 'blob'; xhr.onload = function() { if (xhr.status === 200) { const blob = xhr.response; const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'employee_data.csv'; document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); document.body.removeChild(a); fn_fadeOutWaiting(); } else { console.error("下载请求失败,状态码:", xhr.status); fn_fadeOutWaiting(); } }; xhr.onerror = function() { console.error("下载出错"); fn_fadeOutWaiting(); }; xhr.send();
额外优化:动态获取文件名
如果后端返回的Content-Disposition header里包含文件名,可以通过解析header来动态获取,不用硬编码:
const disposition = response.headers.get('Content-Disposition'); const filenameMatch = disposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); const filename = filenameMatch ? filenameMatch[1].replace(/['"]/g, '') : 'employee_data.csv';
内容的提问来源于stack exchange,提问作者Houy Narun
相关产品推荐
相关产品推荐

