Symfony2 - download file Force

I try to upload a file when the user clicks the download link.

In the controller:

$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; 

This opens a dialog box for saving the file, but it says that the file has 0 bytes. And changing it to:

  $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; 

I get a bunch of weird characters instead of a file download dialog.

Finally, switching the string "setContent" to:

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

It returns a PHP error:

Fatal error: allowable memory size ...

Any clues on how to achieve this? I did this before in PHP (with MVC), but I don’t know what is missing to do this through Symfony2 ...

Maybe the solution sets memory_limit in PHP.INI, but I think this is not the best practice ...

+52
php header symfony download
Oct 22 '12 at 11:23
source share
7 answers

First of all, thank you all for your answers. I finally resolved this without an X-SendFile (which is probably best practice). In any case, for those who cannot make the Apache X-Sendfile module (shared hosting) work, here is the solution:

 // 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)); return $response; 

Hope this helps!

+49
Oct 23 '12 at 7:19
source share

The most convenient solution is

 use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\ResponseHeaderBag; $response = new BinaryFileResponse($file); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT); return $response; 
+84
Dec 03 '15 at 12:13
source share

You should not use PHP to upload files, because this is a task for the Apache or Nginx server. The best way to upload files is to use the X-Accel-Redirect (in the case of Nginx) / X-Sendfile (in the case of Apache) headers.

The following snippet of action can be used with configured Nginx to download files from Symfony2:

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

UPD1: code for Apache with the mod_xsend file configured:

 return new Response('', 200, array( 'X-Sendfile' => $filename, 'Content-type' => 'application/octet-stream', 'Content-Disposition' => sprintf('attachment; filename="%s"', $filename)) ); 
+14
Oct 22 '12 at 11:29
source share

I don't know if it can help, but it is application/octet-stream not application/octect-stream

+8
Oct 22 '12 at 21:13
source share

Starting with Symfony 3.2, you can use the file () controller helper , which is a shortcut to create a BinaryFileResponse , as mentioned in the previous answer:

 public function fileAction() { // send the file contents and force the browser to download it return $this->file('/path/to/some_file.pdf'); } 
+7
Jan 03 '17 at 14:02
source share

+1 for Alexander's answer.

But if you cannot use the X-Sendfile, you must use the BinaryFileResponse added in 2.2: http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files

In my project, the result

 $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; 
+6
Feb 04 '15 at 6:39
source share

For those who do not have the ability to set headers:

The download attribute may help depending on which browsers you need to support:

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

or

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

This is not supported in all legacy browsers. See this page for browser support:

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

+2
Mar 01 '17 at 19:50
source share



All Articles