【问题标题】:Serving file from secure location with Symfony使用 Symfony 从安全位置提供文件
【发布时间】:2015-12-15 13:36:23
【问题描述】:

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

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

这是我读过的几个链接,但没有发现任何明确的内容。

我应该使用__DIR__ 语句吗?

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

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

最后一件事要补充;无法复制我在web文件夹中的文件,有超过10Gb的文件要访问,所以没有缓存,没有复制,只是一个简单的访问。

【问题讨论】:

    标签: php symfony


    【解决方案1】:

    您可以使用以下代码在 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 也可以是绝对路径,但请确保网络服务器可以从该路径读取。只要您使用网络服务器 docroot 之外的路径(可能是 <your app root>/web),您就可以使用投票者和 PHP 中的其他自定义逻辑来控制对文件的访问。

    获取 $file 对象:

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

    $file = new \SplFileInfo($filepath);
    

    为什么选择 BinaryFileResponse?

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

    使用 X-Sendfile:

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

    幸运的是,而不是这个:

    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. 配置您的网络服务器以读取该标头并实际服务器该文件。

    标头的名称以及您的网络服务器的配置方式取决于您使用的网络服务器类型:

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

    【讨论】:

      猜你喜欢
      • 2018-06-19
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 2014-01-26
      • 2014-11-04
      • 1970-01-01
      • 2018-12-30
      • 2013-12-20
      相关资源
      最近更新 更多