使用Symfony从安全位置提供文件

时间:2015-12-15 13:36:23

标签: php symfony

我想从Symfony的服务加载我自己的敏感文件。 我对Symfony文档中的所有内容感到困惑。 默认情况下,我只能访问放在/web文件夹中的文件。

但如果我是对的,这个文件夹是公开的。所以我想将文件移到/src/AppBundle/Resources/myfile.txt

以下是我读过的几个链接,但没有找到任何明确的内容。

我应该使用__DIR__声明吗?

如果可能,我有2个目标要实现:

  • 访问具有项目相对路径的文件(例如AppBundle或'www'文件夹)
  • 访问/random/place/on/my/server中的文件而不暴露整个路径。

最后要添加的内容;没有办法在web文件夹中复制我的文件,有超过10Gb的文件可供访问,所以没有缓存,没有复制,只是一个简单的访问。

1 个答案:

答案 0 :(得分:7)

您可以使用以下代码在Symfony中提供文件:

    $response = new BinaryFileResponse($filepath);

    // Set headers
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-Type', $file->getMimeType());
    $response->headers->set('Content-Disposition', $response->headers->makeDisposition(
        ResponseHeaderBag::DISPOSITION_ATTACHMENT,
        $file->getName()
    ));

    return $response;

确保你也有:

use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

如何获取$file在您已关联的Finder component的文档中有说明。当您将代码放在AppBundle中的控制器中时,您可以使用:

$filepath = __DIR__ . '/../Resources/myfile.txt';

或者您可以使用相对于应用程序根目录的路径:

$rootDir = $this->get('kernel')->getRootDir();
$filepath = $rootDir. '/src/AppBundle/Resources/myfile.txt';

$filepath也可以是绝对路径,但请确保网络服务器可以从该路径读取。只要您使用webservers docroot之外的路径(可能是<your app root>/web),就可以使用PHP中的选民和其他自定义逻辑来控制对文件的访问。

获取$ file对象:

为了构建你的文件对象,你可以使用Finder组件,但这实际上只不过是SPL filehandling的包装器。因此,您也可以使用:

$file = new \SplFileInfo($filepath);

为什么选择BinaryFileResponse?

发送大文件时,PHP可能会在将整个文件作为对客户端的响应发送之前将其读入内存。这可能会导致PHP内存不足。使用BinaryFileResponse通过逐块读取文件并将这些块流式传输到客户端来避免这种情况。因此,永远不要使用Response对象发送大文件。

使用X-Sendfile:

虽然使用上面的代码可以防止PHP内存不足,但在发送文件时仍会使PHP忙碌。如果您有一个繁忙的Web服务器,您可能希望尽可能多地保留PHP进程来呈现网页,而不是流式文件。

Luckely,而不是:

Request ----> Webserver ----> PHP-FPM ----> File
Response <--- Webserver <---- PHP-FPM <---- File

你可以这样做:

Request ----> Webserver ----> PHP-FPM
Response <--- Webserver <---- PHP-FPM
                ^  |
                |  |
                |  V
                File

使用X-Sendfile完成此操作。

这是邪恶的,我该怎么用?

X-Sendfile工作需要两个简单的步骤:

  1. 在您的回复中添加标题,告知您的网络服务器应该为文件提供服务。
  2. 配置您的网络服务器以读取该标头并实际为该文件提供服务。
  3. 标题的名称以及您的网络服务器的配置方式取决于您使用的网络服务器的类型:

    请注意,Nginx将其称为X-Accel。传递给Nginx的标题是X-Accel-Redirect,但这是唯一的区别。