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

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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分