Вы можете служить файл в 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.
Получение $ файла объекта:
Для того, чтобы построить свой объект файла вы можете использовать компонент Finder, но это на самом деле ничего более, что обертка вокруг SPL filehandling.Можно поэтому использовать:
$file = new \SplFileInfo($filepath);
Почему BinaryFileResponse?
При отправке больших файлов PHP может прочитать весь файл в памяти перед отправкой его в качестве ответа клиенту. Это может привести к тому, что у PHP закончится нехватка памяти. Использование BinaryFileResponse
позволяет избежать этого, прочитав файл поблочно и потоковой передачи этих блоков клиенту. Поэтому никогда не отправляйте большие файлы с помощью объекта Response
.
Использование X-SendFile:
При использовании кода выше предотвращает PHP от запуска из памяти, она по-прежнему сохраняет PHP занят во время отправки файла. Когда у вас есть занятый веб-сервер, вы можете захотеть сохранить как можно больше PHP-процессов бесплатно, чтобы отображать веб-страницы, а не потоковые файлы.
Luckely, вместо этого:
Request ----> Webserver ----> PHP-FPM ----> File
Response <--- Webserver <---- PHP-FPM <---- File
Вы можете сделать это:
Request ----> Webserver ----> PHP-FPM
Response <--- Webserver <---- PHP-FPM
^|
| |
| V
File
Это делается с помощью X-Sendfile.
Это нечестиво, как я могу это использовать?
Получение для работы требуется два простых шага:
- Добавление заголовка в своем ответе, что говорит ваш веб-сервер, что он должен сервер файл.
- Настройка вашего веб-сервера для чтения этого заголовка и на самом деле сервера этого файла.
Имя заголовка и, как ваш веб-сервер настроен, зависит от типа веб-сервера, который вы используете:
Заметим, что Nginx называет его X -Accel. Заголовок, который вы передаете Nginx, - X-Accel-Redirect
, но это единственное отличие.