我想从Symfony的服务加载我自己的敏感文件。
我对Symfony文档中的所有内容感到困惑。
默认情况下,我只能访问放在/web
文件夹中的文件。
但如果我是对的,这个文件夹是公开的。所以我想将文件移到/src/AppBundle/Resources/myfile.txt
以下是我读过的几个链接,但没有找到任何明确的内容。
我应该使用__DIR__
声明吗?
如果可能,我有2个目标要实现:
/random/place/on/my/server
中的文件而不暴露整个路径。 最后要添加的内容;没有办法在web文件夹中复制我的文件,有超过10Gb的文件可供访问,所以没有缓存,没有复制,只是一个简单的访问。
答案 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
工作需要两个简单的步骤:
标题的名称以及您的网络服务器的配置方式取决于您使用的网络服务器的类型:
请注意,Nginx将其称为X-Accel。传递给Nginx的标题是X-Accel-Redirect
,但这是唯一的区别。