Symfony2 – скачать файл Force

Я пытаюсь загрузить файл, когда пользователь нажимает ссылку на скачивание.

В контроллере:

$response = new Response(); $response->headers->set('Content-type', 'application/octect-stream'); $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename)); $response->headers->set('Content-Length', filesize($filename)); return $response; 

Это открывает диалоговое окно для сохранения файла, но он говорит, что файл равен 0 байтам. И изменив его на:

  $response = new Response(); $response->headers->set('Content-type', 'application/octect-stream'); $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename)); $response->headers->set('Content-Length', filesize($filename)); $response->headers->set('Content-Transfer-Encoding', 'binary'); $response->setContent(readfile($filename)); return $response; 

Я получаю кучу странных символов вместо диалогового окна загрузки файлов.

Наконец, переключение строки «setContent» на:

  $response->setContent(file_get_contents($filename)); 

Он возвращает ошибку PHP:

Неустранимая ошибка: допустимый размер памяти …

Какие-нибудь подсказки о том, как этого достичь? Я сделал это раньше в PHP (с MVC), но я не знаю, чего не хватает, чтобы сделать это через Symfony2 …

Возможно, решение устанавливает memory_limit в PHP.INI, но я думаю, что это не лучшая практика …

Наиболее удобным решением является

 use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\ResponseHeaderBag; $response = new BinaryFileResponse($file); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT); return $response; 

Прежде всего, спасибо всем за ваши ответы. Я, наконец, решил это без X-SendFile (что, вероятно, является лучшей практикой). В любом случае, для тех, кто не может получить модуль Apache для X-Sendfile для работы (общий хостинг), вот решение:

 // Generate response $response = new Response(); // Set headers $response->headers->set('Cache-Control', 'private'); $response->headers->set('Content-type', mime_content_type($filename)); $response->headers->set('Content-Disposition', 'attachment; filename="' . basename($filename) . '";'); $response->headers->set('Content-length', filesize($filename)); // Send headers before outputting anything $response->sendHeaders(); $response->setContent(file_get_contents($filename)); 

Надеюсь это поможет!

Вы не должны использовать PHP для загрузки файлов, потому что это задача для сервера Apache или Nginx. Лучшим вариантом является использование заголовков X-Accel-Redirect (в случае Nginx) / X-Sendfile (в случае Apache) для загрузки файлов.

Следующий фрагмент действия можно использовать с настроенным Nginx для загрузки файлов из Symfony2:

 return new Response('', 200, array('X-Accel-Redirect' => $filename)); 

UPD1: Код для apache с настроенным файлом mod_xsend:

 return new Response('', 200, array( 'X-Sendfile' => $filename, 'Content-type' => 'application/octet-stream', 'Content-Disposition' => sprintf('attachment; filename="%s"', $filename)) )); 

Не знаю, может ли это помочь, но это application/octet-stream не application/octect-stream

Начиная с Symfony 3.2 вы можете использовать вспомогательный контроллер file (), который является ярлыком для создания BinaryFileResponse как указано в предыдущем ответе:

 public function fileAction() { // send the file contents and force the browser to download it return $this->file('/path/to/some_file.pdf'); } 

+1 для ответа александра.

Но если вы не можете использовать X-Sendfile, вы должны использовать BinaryFileResponse, добавленный в 2.2: http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files

В моем проекте результат

 $response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($dir .DIRECTORY_SEPARATOR. $zipName); $d = $response->headers->makeDisposition( ResponseHeaderBag::DISPOSITION_ATTACHMENT, $zipName ); $response->headers->set('Content-Disposition', $d); return $response; 

Для тех, у кого нет возможности устанавливать заголовки:

Атрибут download может помочь в зависимости от того, какие браузеры вам необходимо поддерживать:

<a href="{file url}" download>

или

<a href="{file url}" download="{a different file name}">

Это не поддерживается во всех устаревших браузерах. См. Эту страницу для поддержки браузера:

https://www.w3schools.com/tags/att_a_download.asp