php Laravel - 在不强制下载的情况下显示存储中的 PDF 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25938294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 18:04:08  来源:igfitidea点击:

Laravel - display a PDF file in storage without forcing download?

phplaravel

提问by Luis Aceituno

I have a PDF file stored in app/storage/, and I want authenticated users to be able to view this file. I know that I can make them download it using

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

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

but I was wondering if there is a way to make them view the file directly in the browser, for example when they are using Google Chrome with the built-in PDF viewer. Any help will be appreciated!

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

回答by Ben Swinburne

Update for 2017

2017 年更新

As of Laravel 5.2 documented under Other response typesyou can now use the file helper to display a file in the user's browser.

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

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

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

Source/thanks to below answer

来源/感谢以下答案

Outdated answer from 2014

2014 年的过时答案

You just need to send the contents of the file to the browser and tell it the content type rather than tell the browser to download it.

您只需要将文件的内容发送到浏览器并告诉它内容类型,而不是告诉浏览器下载它。

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

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

If you use Response::downloadit automatically sets the Content-Disposition to attachment which causes the browser to download it. See this questionfor the differences between Content-Disposition inline and attachment.

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

Edit: As per the request in the comments, I should point out that you'd need to use Responseat the beginning of your file in order to use the Facade.

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

use Response;

Or the fully qualified namespace if Responseisn't aliased to Illuminate's Response Facade.

或者完全限定的命名空间,如果Response不是 Illuminate 的 Response Facade 的别名。

回答by MegaCookie

Since Laravel 5.2 you can use File Responses
Basically you can call it like this:

从 Laravel 5.2 开始,你可以使用File Responses
基本上你可以这样称呼它:

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

and it will display files as PDF and images inline in the browser.

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

回答by Adam Albright

In Laravel 5.5you can just pass "inline" as the dispositionparameter of the download function:

Laravel 5.5 中,您可以将“ inline”作为下载函数的配置参数传递:

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

回答by kreilinger

I am using Laravel 5.4 and response()->file('path/to/file.ext')to open e.g. a pdf in inline-mode in browsers. This works quite well, but when a user wants to save the file, the save-dialog suggests the last part of the url as filename.

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

I already tried adding a headers-array like mentioned in the Laravel-docs, but this doesn't seem to override the header set by the file()-method:

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

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

回答by AARTT

Ben Swinburne's answeris absolutely correct - he deserves the points! For me though the answer left be dangling a bit in Laravel 5.1 which made me research — and in 5.2 (which inspired this answer) there's a a new way to do it quickly.

Ben Swinburne 的回答绝对正确——他应得的分数!对我来说,虽然答案在 Laravel 5.1 中有点悬而未决,这让我进行了研究——而在 5.2(启发了这个答案)中,有一种新的方法可以快速完成。

Note: This answer contains hints to support UTF-8 filenames, but it is recommended to take cross platform support into consideration !

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

In Laravel 5.2 you can now do this:

在 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.
]);

And in Laravel 5.1 you can add above method response()->file()as a fallback through a Service Provider with a Response Macro in the boot method(make sure to register it using its namespace in config/app.phpif you make it a class). Boot method content:

在 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);
});

Some of you don't like Laravel Facades or Helper Methods but that choice is yours. This should give you pointers if Ben Swinburne's answerdoesn't work for you.

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

Opinionated note: You shouldn't store files in a DB. Nonetheless, this answer will only work if you remove the Storagefacade parts, taking in the contents instead of the path as the first parameter as with the @BenSwinburne answer.

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

回答by Mihai Cr?i??

As of laravel 5.5 if the file is stored on a remote storage

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

return Storage::response($path_to_file);

or if it's locally stored you can also use

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

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

I would recommend using the Storage facade.

我建议使用 Storage 门面。

回答by Diamond

Ben Swinburne answer was so helpful.

Ben Swinburne 的回答很有帮助。

The code below is for those who have their PDFfile in database like me.

下面的代码适用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.'"',
]);

Where $pdf->pdfis the file column in database.

$pdf->pdf数据库中的文件列在哪里。

回答by Kayode Ibrahim

Laravel 5.6.*

Laravel 5.6.*

$name = 'file.jpg';

store on image or pdf

存储在图像或 pdf 上

$file->storeAs('public/', $name );

download image or pdf

下载图片或pdf

return response()->download($name);

view image or pdf

查看图片或pdf

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

回答by Shreekanth

Retrieve File name first then in Blade file use anchor(a) tag like below shown. This would works for image view also.

<a href="{{ asset('storage/admission-document-uploads/' . $filename) }}" target="_black"> view Pdf </a>;

首先检索文件名,然后在 Blade 文件中使用 anchor(a) 标签,如下所示。这也适用于图像视图。

<a href="{{ asset('storage/admission-document-uploads/' . $filename) }}" target="_black"> view Pdf </a>;

回答by Miraj Khandaker

Retrieving Files
$contents = Storage::get('file.jpg');

检索文件
$contents = Storage::get('file.jpg');

Downloading Files
return Storage::download('file.jpg');

下载文件
return Storage::download('file.jpg');

File URLs
$url = Storage::url('file.jpg');

文件 URL
$url = Storage::url('file.jpg');