Laravel - 在存储中显示PDF文件而不强制下载?

Lui*_*uno 34 php laravel

我有一个存储在app/storage /中的PDF文件,我希望经过身份验证的用户能够查看此文件.我知道我可以让他们使用它来下载它

return Response::download($path, $filename, $headers);
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有办法让他们直接在浏览器中查看文件,例如当他们使用带有内置PDF查看器的谷歌浏览器时.任何帮助将不胜感激!

Ben*_*rne 72

2017年更新

其他响应类型下记录的Laravel 5.2开始,您现在可以使用文件助手在用户的浏览器中显示文件.

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

return response()->file($pathToFile, $headers);
Run Code Online (Sandbox Code Playgroud)

来源/感谢以下答案

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.'"'
]);
Run Code Online (Sandbox Code Playgroud)

如果您使用Response::download它会自动将Content-Disposition设置为附件,这会导致浏览器下载它.有关Content-Disposition内联和附件之间的差异,请参阅此问题.

编辑:根据评论中的请求,我应该指出您需要use Response在文件的开头才能使用Facade.

use Response;
Run Code Online (Sandbox Code Playgroud)

或者,如果Response没有为Illuminate的Response Facade设置别名,则为完全限定的命名空间.


Meg*_*kie 18

从Laravel 5.2开始,您可以使用文件响应
基本上可以像这样调用它:

return response()->file($pathToFile);
Run Code Online (Sandbox Code Playgroud)

它将在浏览器中以内嵌方式显示PDF和图像文件.


小智 12

Laravel 5.5中,您只需传递" 内联 "作为下载功能的配置参数:

return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');
Run Code Online (Sandbox Code Playgroud)


AAR*_*RTT 6

Ben Swinburne 的回答绝对正确——他应得的分数!对我来说,虽然答案在 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.
]);
Run Code Online (Sandbox Code Playgroud)

在 Laravel 5.1 中,您可以response()->file()通过服务提供者在引导方法中使用响应宏添加上述方法作为后备(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);
});
Run Code Online (Sandbox Code Playgroud)

你们中的一些人不喜欢 Laravel Facades 或 Helper Methods,但该选择是你的。如果本·斯威本 (Ben Swinburne) 的回答对您不起作用,这应该会给您一些提示。

意见建议:您不应该将文件存储在数据库中。尽管如此,这个答案只有在您删除Storage外观部分时才有效,将内容而不是路径作为第一个参数,就像@BenSwinburne 的答案一样。


小智 5

我正在使用 Laravel 5.4 并response()->file('path/to/file.ext')在浏览器中以内联模式打开例如 pdf。这很有效,但是当用户想要保存文件时,保存对话框会建议将 url 的最后一部分作为文件名。

我已经尝试添加一个像 Laravel-docs 中提到的 headers-array,但这似乎并没有覆盖由 file()-method 设置的标头:

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


Mih*_*iță 5

从 laravel 5.5 开始,如果文件存储在远程存储上

return Storage::response($path_to_file);
Run Code Online (Sandbox Code Playgroud)

或者如果它是本地存储的,您也可以使用

return response()->file($path_to_file);
Run Code Online (Sandbox Code Playgroud)

我建议使用 Storage 门面。