2017-07-07 173 views
9

我有一個Laravel 5.4應用程序,其中經過身份驗證的用戶需要能夠從S3存儲下載私人文件。我已經設置了一個路由和控制器來允許私人文件下載。Laravel 5文件下載:流()或下載()

的代碼看起來是這樣的:

路線:

控制器:

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', 
    ]); 
} 

所有工作正常,但是當我定睛一看至Laravel docs,我發現,他們只是談論response()->download()

如果我實現了樣的反應,我的代碼是這樣的:

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), 
    ]); 
} 

這兩個功能可以在API docs找到。

我的問題:什麼是首選方式,每種方式的優缺點是什麼?

從我迄今收集:

流:

  • 不需要將整個文件加載到內存中
  • 適合大文件

下載:

  • 需要更少的代碼
+0

謝謝! –

+0

@ jones03請參閱此答案https://stackoverflow.com/a/24008078 – Qh0stM4N

回答

1

當你調用Laravel的response()幫手,它返回Illuminate\Routing\ResponseFactory的一個實例。 ResponseFactory有這兩種方法:downloadstream - 有問題的兩種方法。如果你深入挖掘一下,你會發現download返回一個\Symfony\Component\HttpFoundation\BinaryFileResponse的實例,而stream返回一個\Symfony\Component\HttpFoundation\StreamedResponse - 這些都是Symfony組件。

在這裏通過代碼挖掘是沒有必要的,但是很好理解底層發生了什麼。現在我們知道返回的底層對象來自Symfony HTTP組件,我們可以參考Symfony文檔並查看他們推薦使用的內容。通常情況下,當文件的大小未知時(例如當您在運行中生成文件時)使用流。在其他大多數情況下,由download方法生成的BinaryFileResponse將足以滿足您的需求。

您可以查看HTTP Streaming及其使用案例here的更深入的解釋。