CodeIgniter中调用force_download后如何实现页面刷新?
解决CodeIgniter中force_download后后续代码不执行的问题
兄弟,你碰到的这个问题其实是CodeIgniter的force_download()函数的特性导致的——这个函数在输出文件内容后会直接调用exit()终止整个脚本,所以你写在它后面的数据库更新和页面跳转代码根本没机会运行。
下面给你两种可行的解决方案,根据你的需求来选:
方案1:先统计下载点击量,再引导下载+页面跳转(适合统计点击次数)
这种方法会先更新数据库(统计用户的下载点击行为),然后通过HTML元刷新让用户同时开始下载并跳回原页面:
public function download(){ $this->load->library('user_agent'); $file_id = $this->uri->segment(3); if(!empty($file_id)){ // 先更新下载量(这里统计的是用户点击下载的次数) $this->Files->update_download($file_id); // 获取文件信息,优化取值方式,不用冗余的foreach $fileInfo = $this->Files->get_file($file_id); if(empty($fileInfo)){ // 文件不存在时直接跳回原页面 redirect($this->agent->referrer() ?: base_url()); return; } $download_direc = $fileInfo[0]->file_direc; $file_url = base_url($download_direc); $referrer_url = $this->agent->referrer() ?: base_url(); // 输出一个中间过渡页面,引导下载并自动跳转 echo '<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>准备下载</title> <!-- 立即触发文件下载 --> <meta http-equiv="refresh" content="0; url='.$file_url.'"> <!-- 1秒后跳回原页面 --> <meta http-equiv="refresh" content="1; url='.$referrer_url.'"> </head> <body> <p>正在准备下载文件...如果下载未自动开始,请<a href="'.$file_url.'">点击这里</a></p> <p>即将返回原页面...</p> </body> </html>'; } else { redirect($this->agent->referrer() ?: base_url()); } }
方案2:自定义下载逻辑,确保下载完成后更新数据库(适合统计实际下载完成量)
如果你需要统计用户实际完成下载的次数,可以自己实现文件输出逻辑,代替force_download(),这样文件输出完成后就能执行后续代码:
public function download(){ $this->load->library('user_agent'); $file_id = $this->uri->segment(3); if(!empty($file_id)){ $fileInfo = $this->Files->get_file($file_id); if(empty($fileInfo)){ redirect($this->agent->referrer() ?: base_url()); return; } $download_direc = $fileInfo[0]->file_direc; // 拼接完整的服务器文件路径,FCPATH是CodeIgniter提供的网站根目录常量 $file_path = FCPATH . ltrim($download_direc, '/'); if(!file_exists($file_path)){ redirect($this->agent->referrer() ?: base_url()); return; } // 设置HTTP响应头,告诉浏览器这是需要下载的文件 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file_path).'"'); header('Content-Length: '.filesize($file_path)); // 禁用缓存,避免旧文件干扰 header('Cache-Control: no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); header('Expires: 0'); // 输出文件内容到客户端 readfile($file_path); // 文件输出完成后,更新数据库下载量 $this->Files->update_download($file_id); // 注意:这里的redirect不会生效,因为已经输出了文件内容 // 如果需要跳转,还是得结合方案1的中间页方式,或者让前端通过AJAX处理 } else { redirect($this->agent->referrer() ?: base_url()); } }
补充说明
- 方案1的优点是简单可靠,适合大多数场景,缺点是统计的是点击量而非实际下载完成量;
- 方案2可以统计实际完成下载的次数,但如果用户中途取消下载,服务器可能已经完成了文件输出,还是会更新数据库(取决于服务器的连接处理机制);
- 如果需要精确统计实际下载完成量,最可靠的方式是前端通过JavaScript监听下载完成事件,然后发送AJAX请求到后端更新数据库,但这种方式需要处理跨域等问题,且依赖前端环境。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

