如何用PHP+JavaScript实现文件下载并监听下载完成事件
通用文件下载+完成事件监听解决方案
核心思路
用PHP做跨域代理解决第三方URL的CORS问题,同时通过隐藏<iframe>加载代理地址,利用iframe的load事件监听下载完成并触发自定义逻辑。这个方案无需处理编码后的文件内容,直接让浏览器处理原生下载流程,同时满足跨域和事件监听需求。
实现步骤
1. 后端PHP代理(解决跨域)
创建download-proxy.php文件,负责转发请求并返回正确的文件响应头:
<?php $targetUrl = $_GET['url'] ?? ''; if (empty($targetUrl)) exit('无效的文件地址'); // 用cURL处理请求(兼容性更好,不受allow_url_fopen限制) $ch = curl_init($targetUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 处理重定向 curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); if (curl_errno($ch)) exit('请求文件失败:' . curl_error($ch)); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $headerSize); $fileContent = substr($response, $headerSize); // 提取并设置必要的响应头 foreach (explode("\r\n", $headers) as $header) { $header = trim($header); if (strpos($header, 'Content-Type:') === 0 || strpos($header, 'Content-Length:') === 0) { header($header); } } // 强制触发浏览器下载 header('Content-Disposition: attachment; filename="' . basename(parse_url($targetUrl, PHP_URL_PATH)) . '"'); echo $fileContent; curl_close($ch); exit; ?>
2. 前端JS实现下载+监听
通过动态创建隐藏iframe,加载代理地址并监听完成事件:
function downloadAndNotify(fileUrl, onComplete) { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; // 监听加载完成事件(文件下载触发后,iframe会触发load) iframe.addEventListener('load', () => { onComplete(); // 清理iframe避免内存占用 document.body.removeChild(iframe); }); // 构造代理请求地址,编码目标URL避免参数错误 iframe.src = `download-proxy.php?url=${encodeURIComponent(fileUrl)}`; document.body.appendChild(iframe); } // 使用示例 downloadAndNotify('https://example.com/your-file.pdf', () => { console.log('文件下载完成!'); // 这里写入你的自定义逻辑:比如弹出提示、更新页面状态等 });
关键说明
- 跨域解决:服务器端请求不受浏览器CORS限制,PHP代理作为中间层转发请求,规避前端跨域问题。
- 事件监听:iframe的
load事件会在服务器返回响应后触发,无论文件是直接打开还是下载,都能准确捕获完成状态。 - 兼容性:支持所有现代浏览器,无需依赖第三方库,逻辑简单易维护。
内容的提问来源于stack exchange,提问作者Mahesh Thorat
相关产品推荐
相关产品推荐

