Yii2:发送响应内容后refresh()无法正常工作

时间:2018-05-09 11:57:52

标签: 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);
}

1 个答案:

答案 0 :(得分:1)

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

在Yii 2.0.14之前,有一个错误和框架被忽略,你试图在内容发送后发送标题。如果升级Yii,在这种情况下你应该得到“好”的异常。

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