首页 > 解决方案 > Yii2:发送响应内容后刷新()不起作用

问题描述

我有一个ActiveForm用来从中获取一些数据的工具,当我单击发送按钮时,它将运行模型(在本例中为 csv 文件生成器),但刷新不起作用,当我删除该方法时它会刷新。

经过一些测试后,似乎fputcsv()会停止脚本,因此之后的所有内容都不会运行。

看法

public function actionIndex()
{
    $model = new Export();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
        $fields = Yii::$app->request->post('Export');

        \backend\models\Export::generate();//this prevents the refresh

        Yii::$app->session->setFlash();

        return $this->refresh();
    } else {
        return $this->render('index' , ['model' => $model]);
    }
}

模型

static public function generate() 
{
    header('Content-Encoding: UTF-8');
    header('Content-Type: text/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="sample.csv"');
    header("Pragma: no-cache");
    header("Expires: 0");

    $data = [array comes here];
    $fp = fopen('php://output', 'w') or die("Unable to open file!");
    fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));

    foreach ( $data as $line ) {
        fputcsv($fp , $line , ';' );
    }

    stream_get_contents($fp);
    fclose($fp);
}

标签: yii2

解决方案


Controller::refresh()使用Location标题重新加载页面。由于标头需要在内容之前,因此您不能在发送内容后添加新标头。您的Export::generate()方法发送内容,因此您不能在此之后添加任何标题,因此$this->refresh()不起作用。

在 Yii 2.0.14 之前,有一个错误,框架简单地忽略了您在发送内容后尝试发送标头。如果你升级 Yii,在这种情况下你应该得到 "nice" 异常。


如果您在下载文件后尝试显示漂亮的页面,那么您的方法是不正确的。您不能真正返回文件,然后重定向到不同的页面。您应该首先显示漂亮的 HTML 页面,并在其中将用户重定向到下载页面(例如通过使用<meta http-equiv="refresh" content="0; url=http://example.com/" />in head 或创建隐藏表单并通过 JavaScript 提交)。下载文件后,用户将停留在这个漂亮的页面上,所以从用户体验的角度来看,一切都应该没问题。


推荐阅读