Set Response from controller action (avoid White Screen)

Hello. I have a controller action that returns a file (most of the time), but when the file is empty, I don’t wanna return that, and I wanna get the (index) view untouched (like when the action returns a file with content).
How I can do that? I tried all, and allways get a white screen (but without any errors).
Thanks

I cannot pretend I understood well what you said, but what about checking if the file is empty and redirect to some other action?

Hello Stefano, and thanks.
If the file is empty, I don’t wanna return nothing and keep the actual view without refresh. How I do that? Thanks

public function actionDownloadFile()
{
    $file = "something done here";
    if($file != null)//or any empty file check 
    {
        return $file;//do your file stuffs
    }

    return $this->render('myview', ['somedata' => $data]);
}

Stefano, the “render” function refresh the page. I have a index view with filters applied by the user. I don’t wanna change the view. I wanna do “nothing” when the file is empty.

BTW, when I donwload a file, is exactly what happens … the view keeps unchanged. I wanna reply this but when nothing is downloaded.

How do you navigate to download file?

I call to an action from the view:

Html::a(’’.Yii::t(‘app’, ‘Export PRO’),[‘export-all’], [‘target’ => ‘_blank’]])

In the action controller:

$pdf = new \kartik\mpdf\Pdf([ …
return $pdf->render();

So where are you checking if the file is empty?
Because if it is empty then it will show blank screen and when download succeeds it will close that tab automatically

In the action I check when the file is empty. Then … What I must do in this case for not open the white tab (or close it immediately)?

By that time it is too late!
I would suggest you check existence of the file in the action that renders the link. And render the link if file exists and message otherwise.

Another way would be to render file in the same action something like

class MyController extends Controller
{
    public function actionDownloadFile($id, $download = 0)
    {
        if ($download == 1) {
            $file = "something done here";
            if ($file != null) //or any empty file check
            {
                return $file; //do your file stuffs
            } else {
                Yii::$app->session->setFlash('danger', 'Failed to download for some reason!');
            }
        }

        return $this->render('myview', ['somedata' => $data]);
    }
}

then in the view

<?= Html::a('Download File', ['download-file', 'id' => $data['id'], 'download' => 1]) ?>

HTH

I tried status code 204 (no content). It seems to work as intended if the [‘target’ => ‘_blank’] is omitted.

In the controller action I added:
Yii::$app->getResponse()->setStatusCode(204);

(perhaps also return null)

2 Likes

Thanks Tommy. But when I send a PDF I need to open it in a new tab (then *[‘target’ => ‘_blank’] is required.

Any other idea? Thanks

You didn’t work on the idea I gave above!

Hello Stefano.
When you do:

return $this->render(‘myview’, [‘somedata’ => $data]);

The page is refreshed and the user lost all your selected filters.

A bit more complicated, but I think you can do this with Ajax.

First an Ajax call for finding out if the file is ok. (Save selected file id, locally I guess.)
On return, programmatically click a hidden link for creating the pdf and spawn the new window with target=_blank.

Just an idea.

Edit: I had missed to add target=_blank. Obviously this will not pass the popup blocking. Thus as bad as w=window.open, which is required for w.close() to work.

You have to preserve filters yourself.
Since you have not posted how you do things, I can guess thus far!

you can return JSON response and if not empty open it with js in new window. If empty just prevent default event