Headers already sent when using codemix\excelexport\ExcelFile

Hi.
I’m exporting an excel file with the above extension. And everything works fine, the file is generated correctly! But in app log I get the following:

2019-02-21 18:30:58 [x.x.x.x][1][-][error][yii\web\HeadersAlreadySentException] yii\web\HeadersAlreadySentException: Headers already sent. in vendor/yiisoft/yii2/web/Response.php:366
Stack trace:
#0 vendor/yiisoft/yii2/web/Response.php(339): yii\web\Response->sendHeaders()
#1 vendor/yiisoft/yii2/base/Application.php(392): yii\web\Response->send()
#2 web/index.php(14): yii\base\Application->run()
#3 {main}

The controller code:

         if ($model->load(Yii::$app->request->post()) && $model->validate()) {
             $estrai = $model->estrai();
             if (empty($estrai)) {
                 Yii::$app->session->setFlash('warning', Yii::t('app', "Nessun dato trovato per il periodo selezionato"));
             } else {
                 // Intestazioni foglio excel
                 $file = \Yii::createObject([
                     'class' => \codemix\excelexport\ExcelFile::class,
                     'sheets' => [
                         'Giacenze' => [
                             'data' => $estrai,
                             'titles' => $model->intestazioni_xls(),
                         ],
                     ],
                 ]);
                 // Invio al browser
                 $file->send(date("Y.m.d H.i.s")." Costo deposito {$model->intervallo_date} zone ".implode(" ", $model->zone).".xls");
             }
         }

         return $this->render('/deposito/esporta-costi', [
             'model' => $model,
         ]);

I tried adding return and Yii::$app->end() right after the send() but the error is printed anyway (a little different, tough).

Again, the file is sent to the client and correctly downloaded, but the error above is logged to file. What could it be?
thanks

Check your PHP files for blank lines before <?php. Is it only happening in that particular controller action or indepdently of the path (I assume the latter?).

Actually it happens just in that single action. The controller has no heading spaces, neither the model. They contain no echo or similar outputting calls.

What I don’t really get is why it’s throwing that error but also sending the file! If headers are already sent the file download shouldn’t start correctly, unless the browser is ignoring the first ones.

I think that what’s going on is that the file is output, then yii try to print the action response, so it tries to set it headers which fails.

Try using return $file->send(...

good idea but it doesn’t work, the error is still logged.

indeed I already tried adding the return just after the send

Ideally the library would return the generated output, and you would return it from the action.

Since it’s not the case, try adding You::$app->end(); after the send to end the yii lifecycle.

as I wrote in the first post I already did that but it still throws the error

A simple exit() after $file->send() may work, I guess.

1 Like

It worked! Thanks!!

Wondering why… Yii::$app->end() should do the same, isn’t it? There could be something throwing some output before Yii ends its runtime…?

It’s a kind of mismatch between Yii 2 and the library.

\codemix\excelexport\ExcelFile::send() (or, precisely speaking, \mikehaertl\tmp\File::send() which is a dependency of the library) sends the response (the headers and the file content) by itself.

This is not a kind of behavior that Yii 2 expects from a library, because it is the framework that should send the response, as @machour says in a reply:

As you see in the source code of yii\base\application\end(), it is possible that Yii::$app->end() may send some headers trying to terminate the application in a decent manner.