dongyin6576
2017-07-07 08:11
浏览 792
已采纳

Laravel 5文件下载:stream()或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
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dpwgzi7987 2018-01-09 18:44
    已采纳

    When you call Laravel the 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.

    点赞 评论

相关推荐 更多相似问题