You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

window.open加载事件未触发:PDF下载后无法关闭加载图标

问题:window.open加载PDF下载链接时load事件不触发,无法控制加载图标

我想用window.open打开PDF下载链接前显示加载图标,但没法等下载完成后关闭图标。代码如下:

let window_open = window.open("api/dummyGenerateAdhocTicketPDF?download="+download+"&client_id="+client_id+"&user_id="+user_id+"&manual_ticket_id_array="+manual_ticket_id);
window_open.addEventListener('load', function(){console.log("TESTING")}, false);

加载事件从未触发,控制台没输出TESTING,但PDF能正常下载。


编辑补充:
我把window.open的URL换成www.google.com时,load事件正常触发,所以怀疑是Laravel控制器返回下载响应的方式有问题,控制器代码:

return response()->download($tmpFile)->deleteFileAfterSend(true);

原因分析

浏览器收到response()->download()返回的文件下载响应时,不会在新打开的窗口里渲染任何内容——浏览器直接处理下载请求,新窗口要么请求完成后立刻关闭,要么保持空白但不会触发load事件(因为没有实际页面内容加载)。而打开普通网页时,浏览器会加载完整的DOM结构,所以load事件能正常触发。

解决方案

方案一:用Fetch/XMLHttpRequest替代window.open(推荐)

直接发起请求监听完成状态,自己处理文件下载,这样就能精准控制加载图标的显示和隐藏:

// 显示加载图标
showLoadingSpinner();

fetch(`api/dummyGenerateAdhocTicketPDF?download=${download}&client_id=${client_id}&user_id=${user_id}&manual_ticket_id_array=${manual_ticket_id}`, {
  credentials: 'include' // 如果接口需要登录态,加上这个
})
  .then(response => {
    if (!response.ok) throw new Error('请求失败');
    return response.blob();
  })
  .then(blob => {
    // 创建临时下载链接
    const url = window.URL.createObjectURL(blob);
    const downloadLink = document.createElement('a');
    downloadLink.href = url;
    downloadLink.download = 'ticket.pdf'; // 自定义下载文件名
    document.body.appendChild(downloadLink);
    downloadLink.click();
    // 清理临时资源
    window.URL.revokeObjectURL(url);
    document.body.removeChild(downloadLink);
    // 关闭加载图标
    hideLoadingSpinner();
  })
  .catch(err => {
    console.error('下载出错:', err);
    hideLoadingSpinner();
  });

方案二:通过中转页面间接触发下载(保留window.open)

如果一定要用window.open,可以让后端先返回一个中转页面,在页面里触发下载后通知父窗口关闭加载图标:

  1. 修改Laravel控制器,返回中转视图:
return view('download_redirect', ['filePath' => $tmpFile]);
  1. 创建resources/views/download_redirect.blade.php视图文件:
<script>
// 触发文件下载
const downloadLink = document.createElement('a');
downloadLink.href = "{{ route('temp.download', ['file' => basename($filePath)]) }}"; // 要先定义一个能访问临时文件的路由
downloadLink.download = 'ticket.pdf';
downloadLink.click();

// 通知父窗口关闭加载图标
if (window.opener && typeof window.opener.hideLoadingSpinner === 'function') {
  window.opener.hideLoadingSpinner();
}

// 延迟关闭当前窗口,确保下载触发完成
setTimeout(() => window.close(), 300);
</script>

需要额外定义一个路由来提供临时文件的访问权限,同时注意清理临时文件的逻辑。

内容的提问来源于stack exchange,提问作者Yeo Bryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:02:34