Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincent15000's avatar

laravel-dompdf : stream() not working since used in a service instead of a controller

Hello,

I have updated the code of an application.

I used $pdf->stream() directly in the controller and I moved this code to a service.

public function training(Training $training, $download = true)
{

    $this->authorize('export', $training);
        
    (new FileService)->training($training, true);
}
public function training(Training $training, $download = true)
{
    $employees = $training->employees->sortBy(['lastname', 'firstname']);

    $pdf = PDF::loadView('files.training', compact('training', 'employees'));
    $pdf->setPaper('a4', 'portrait');
    if ($download) {
        return $pdf->stream($training->society->name.' - '.$training->name.'.pdf');
    } else {
        $folder = storage_path('app/documents/'.$training->id);
        if (!is_dir($folder)) {
            mkdir($folder, 0700, false);
        }
        $pdf->save(storage_path('app/documents/'.$training->id.'/file.pdf'));
    }
}

Now the stream functionality doesn't work any more and the PDF page is white.

I just checked what happens if I move the service code back to the controller function and it works fine.

In my mind, no matter if the code is directly in the controller or in a service, it should work.

Can you help me understand why it doesn't work ?

Thanks a lot.

Vincent

0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

When you move the PDF generation and streaming logic from a controller to a service, you need to ensure that the service method returns the response back to the controller, which then returns it to the client. In your current setup, it seems like the service method is not returning the PDF stream response, which is why the PDF page appears white.

Here's how you can modify your code to ensure the response is properly returned:

  1. Modify the Service Method: Ensure that the training method in your FileService returns the PDF stream.
public function training(Training $training, $download = true)
{
    $employees = $training->employees->sortBy(['lastname', 'firstname']);

    $pdf = PDF::loadView('files.training', compact('training', 'employees'));
    $pdf->setPaper('a4', 'portrait');
    if ($download) {
        return $pdf->stream($training->society->name.' - '.$training->name.'.pdf');
    } else {
        $folder = storage_path('app/documents/'.$training->id);
        if (!is_dir($folder)) {
            mkdir($folder, 0700, false);
        }
        $pdf->save(storage_path('app/documents/'.$training->id.'/file.pdf'));
    }
}
  1. Modify the Controller Method: Ensure that the controller method captures and returns the response from the service.
public function training(Training $training, $download = true)
{
    $this->authorize('export', $training);
    
    return (new FileService)->training($training, $download);
}

By returning the result of the stream() method from the service back to the controller, and then from the controller to the client, you should be able to see the PDF as expected. This ensures that the HTTP response is properly handled and sent back to the browser.

1 like
jameswise's avatar

The issue likely arises from the way the response is being handled when you move the PDF streaming to a service. In your controller, when you return $pdf->stream(), it directly sends the response to the browser. However, when you call this from a service, the response might not be properly returned to the client because services typically don't handle HTTP responses.

To fix this, ensure that the service method returns the response back to the controller, and then your controller should return that response to the client. Modify your service method to return $pdf->stream(), and ensure that your controller returns the result of the service call. Here's a quick example:

public function training(Training $training)
{
    $this->authorize('export', $training);
    
    return (new FileService)->training($training, true);
}

And in your FileService:

public function training(Training $training, $download = true)
{
    $employees = $training->employees->sortBy(['lastname', 'firstname']);
    
    $pdf = PDF::loadView('files.training', compact('training', 'employees'));
    $pdf->setPaper('a4', 'portrait');
    
    if ($download) {
        return $pdf->stream($training->society->name.' - '.$training->name.'.pdf');
    } else {
        $folder = storage_path('app/documents/'.$training->id);
        if (!is_dir($folder)) {
            mkdir($folder, 0700, false);
        }
        $pdf->save(storage_path('app/documents/'.$training->id.'/file.pdf'));
    }
}

Make sure the service method returns what you need in the controller to send it back to the client.

1 like

Please or to participate in this conversation.