Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 file downloads: stream() or download()

I have a Laravel 5.4 app where authenticated users need to be able to download private files from S3 storage. I've setup a route and controller to allow private file downloads.

The code looks like this:

Route:

Route::get('file/{filename}', 'FileController@download')->where(['filename' => '[A-Za-z0-9-._\/]+'])->name('file')->middleware('auth:employee');

Controller:

public function download($fileName)
{
    if (!$fileName || !Storage::exists($fileName)) {
        abort(404);
    }

    return response()->stream(function() use ($fileName) {
        $stream = Storage::readStream($fileName);
        fpassthru($stream);
        if (is_resource($stream)) {
            fclose($stream);
        }
    }, 200, [
        'Cache-Control'         => 'must-revalidate, post-check=0, pre-check=0',
        'Content-Type'          => Storage::mimeType($fileName),
        'Content-Length'        => Storage::size($fileName),
        'Content-Disposition'   => 'attachment; filename="' . basename($fileName) . '"',
        'Pragma'                => 'public',
    ]);
}

All working fine, but when I had a closer look to the Laravel docs, I found that they just talk about response()->download().

If I implement that kind of response, my code would look like this:

public function download($fileName)
{
    if (!$fileName || !Storage::exists($fileName)) {
        abort(404);
    }

    $file = Storage::get($fileName);

    return response()->download($file, $fileName, [
        'Content-Type'  => Storage::mimeType($fileName),
    ]);
}

Both functions can be found in the API docs.

My question: what would be the preferred way to go and what are the advantages/disadvantages of each?

From what I've gathered so far:

Stream:

  • Does not require the whole file to be loaded into memory
  • Suitable for large files

Download:

  • Requires less code
like image 487
Jones03 Avatar asked Jul 07 '17 08:07

Jones03


People also ask

How can I download Laravel files?

Downloading files in Laravel is even more simple than uploading. You can pass download() method with file path to download file. Same way, if you want to download file from the public folder, you can use download() method from Response class.

What is Laravel stream?

stream-laravel is a Laravel client for Stream. You can use this in any Laravel application, or in any application that uses Eloquent ORM ( illuminate/database ) as a standalone ORM. You can sign up for a Stream account at https://getstream.io/get_started.

How do I delete files from storage in Laravel?

One way to delete a file from the public directory in Laravel is to use the Storage facade. To delete a file, you will need to follow the following steps: Step 1: Check to ensure that the folder and file exist. Step 2: Delete the required file.


1 Answers

When you call the Laravel response() helper, it returns an instance of the Illuminate\Routing\ResponseFactory. The ResponseFactory has these two methods: download and stream - the two methods in question. If you dig a little bit deeper, you'll see that download returns an instance of \Symfony\Component\HttpFoundation\BinaryFileResponse, while stream returns a \Symfony\Component\HttpFoundation\StreamedResponse - these are both Symfony components.

Digging through the code here isn't necessary, but it is nice to have an understanding of what's going on under the hood. Now that we know the underlying objects returned are from the Symfony HTTP Component, we can consult the Symfony docs and see what they recommend using. Typically, streams are used when the size of the file is unknown, such as when you are generating the file on the fly. In most other cases, the BinaryFileResponse generated by the download method will be sufficient for your needs.

You can take a look at a much more in-depth explanation of HTTP Streaming and its use cases here.

like image 153
samrap Avatar answered Sep 27 '22 22:09

samrap