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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:37