2014-09-19 63 views
26

我有一個PDF文件存儲在app/storage /中,並且我希望經過身份驗證的用戶能夠查看此文件。我知道,我可以讓他們使用Laravel - 在不強制下載的情況下在存儲器中顯示PDF文件?

return Response::download($path, $filename, $headers); 

下載它,但我不知道是否有一種方法,使當他們使用谷歌Chrome瀏覽器與他們在瀏覽器中直接查看該文件,例如內置PDF查看器。任何幫助將不勝感激!

+1

我相信你想'響應::使($ PDF,statusC ode,array('content-type'=>'application/pdf'))'。 – Ohgodwhy 2014-09-19 16:21:48

+0

這幫助我走上正軌,謝謝! @ ben-swinburne在下面發佈了正確的答案,我已經接受了。 – 2014-09-23 12:54:18

回答

49

2017年

更新作爲Laravel 5.2 Other response types記錄下你現在可以使用文件助手來顯示在用戶的瀏覽器中的文件。

return response()->file($pathToFile); 

return response()->file($pathToFile, $headers); 

Source/thanks to below answer

過時的答案從2014年起

你只需要在文件的內容發送到瀏覽器,並告訴它的內容類型,而不是讓瀏覽器下載。

$filename = 'test.pdf'; 
$path = storage_path($filename); 

return Response::make(file_get_contents($path), 200, [ 
    'Content-Type' => 'application/pdf', 
    'Content-Disposition' => 'inline; filename="'.$filename.'"' 
]); 

如果使用Response::download它會自動將內容處置依戀這將導致瀏覽器下載。有關Content-Disposition內聯和附件之間的差異,請參閱this question

編輯:根據評論中的要求,我應該指出,爲了使用Facade,您需要在文件的開始處使用use Response

use Response; 

或完全合格的命名空間,如果Request沒有別名照亮的迴應門面。

+0

你的方法不適用於'.txt'文件。它下載文件。 – 2016-01-31 12:18:46

+0

想必您將內容類型更改爲text/plain? – 2016-01-31 12:27:27

+0

爲了幫助,請記住,您可以使用'storage_path()'助手而不需要串聯:'$ path = storage_path('app/file.txt')'。請參閱https://laravel.com/docs/5.2/helpers#method-storage-path – AARTT 2016-03-16 12:36:51

2

Ben Swinburne的回答非常有幫助。

下面的代碼適用於那些在我的數據庫中有PDF文件的人。

$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first(); 

return Response::make(base64_decode($pdf->pdf), 200, [ 
    'Content-Type' => 'application/pdf', 
    'Content-Disposition' => 'inline; filename="'.$filename.'"', 
]); 

其中$pdf->pdf是數據庫中的文件列。

+0

你的內容處置也是錯誤的。它應該是''Content-Disposition'=>'內聯; filename =「'。$ filename。'」''假設文件名不包含引號。請參閱https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1 – Tobia 2016-04-22 08:34:40

+0

將文件內容存儲在數據庫中的任何人都應該返回學校/大學,並瞭解到這是一種可怕的做法。 – ash 2016-04-22 10:02:57

+2

@ash我傾向於同意,出於實際的原因。 (管理小型數據庫和文件目錄比管理包含文件內容的巨大數據庫更容易;思考rsync,備份等)但是,您不應該這樣做。將文件存儲在數據庫中在許多情況下都有實際用途。 – Tobia 2016-04-23 18:47:44

3

Ben Swinburne's answer是絕對正確的 - 他值得點!對我來說,雖然答案留在Laravel 5.1中讓我感興趣,並且在5.2版中(這啓發了這個答案),但有一種新的方法可以快速完成。

注意:此答案包含支持UTF-8文件名的提示,但建議考慮跨平臺支持!

在Laravel 5.2現在你可以這樣做:

$pathToFile = '/documents/filename.pdf'; // or txt etc. 

// when the file name (display name) is decided by the name in storage, 
// remember to make sure your server can store your file name characters in the first place (!) 
// then encode to respect RFC 6266 on output through content-disposition 
$fileNameFromStorage = rawurlencode(basename($pathToFile)); 

// otherwise, if the file in storage has a hashed file name (recommended) 
// and the display name comes from your DB and will tend to be UTF-8 
// encode to respect RFC 6266 on output through content-disposition 
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf'); 

// Storage facade path is relative to the root directory 
// Defined as "storage/app" in your configuration by default 
// Remember to import Illuminate\Support\Facades\Storage 
return response()->file(storage_path($pathToFile), [ 
    'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"), 
    'Content-Type'  => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc. 
]); 

而且在Laravel 5。1,您可以將上述方法response()->file()添加爲a Response Macro in the boot method服務提供商的回退(如果您將其設爲類,請務必使用其名稱空間在config/app.php中進行註冊)。啓動方法內容:

// Be aware that I excluded the Storage::exists() and/or try{}catch(){} 
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) { 

    // Storage facade path is relative to the root directory 
    // Defined as "storage/app" in your configuration by default 
    // Remember to import Illuminate\Support\Facades\Storage 
    $storagePath   = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration 
    $fileContents  = Storage::get($storagePath); 
    $fileMimeType  = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc. 
    $fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension 

    $headers = array_merge([ 
     'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"), 
     'Content-Length'  => strlen($fileContents), // mb_strlen() in some cases? 
     'Content-Type'  => $fileMimeType, 
    ], $userHeaders); 

    return $factory->make($fileContents, 200, $headers); 
}); 

你們有些人不喜歡Laravel Facades或Helper Methods,但這個選擇是你的。如果Ben Swinburne's answer不適合你,這應該會給你指示。

意見說明:您不應將文件存儲在數據庫中。儘管如此,只有在您刪除了Storage外觀部件時,此答案纔有效,將內容而不是第一個參數的內容視爲@BenSwinburne答案。

+0

您的內容處置也是錯誤的。它應該是''Content-Disposition'=>'內聯; filename =「'。$ filename。'」''假設文件名不包含引號。見https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1 – Tobia 2016-04-22 08:35:01

+0

@託比亞感謝您的輸入!如果文件名包含空格,保留字符或非ASCII/ISO-8859-1字符,引號就很重要。有一個'filename *'選項,它將需要[RFC 5987](https://tools.ietf.org/html/rfc5987)中指定的編碼。 [RFC 6266 Sec-5有更多的例子](https://tools.ietf.org/html/rfc6266#section-5)。但是,尊重[跨平臺文件名限制](https://en.wikipedia.org/wiki/Filename)(較老的更受限制的),對於大多數平臺而言這不會成爲問題。我會爲PHP解決方案記住您的建議並更新我的答案! – AARTT 2016-04-23 10:39:08

15

由於Laravel 5.2,你可以使用File Responses
基本上你可以這樣調用:

return response()->file($pathToFile); 

,它會在瀏覽器中內嵌顯示文件爲PDF格式和圖像。

3

我使用Laravel 5.4和response()->file('path/to/file.ext')打開例如瀏覽器內嵌模式的pdf。這工作得很好,但是當用戶想要保存文件時,保存對話框會將url的最後部分建議爲文件名。

我已經嘗試添加一個報頭陣列像Laravel-文檔提到的,但這似乎並不覆蓋頭由文件()設置 - 方法:

return response()->file('path/to/file.ext', [ 
    'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"' 
]); 
4

Laravel 5.5你可以通過「在線」的下載功能的配置參數:

return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline'); 
相關問題