Symfony2 – 强制文件下载
我试图在用户点击下载链接时下载文件。
在控制器中:
$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做到这一点…
也许解决scheme是在PHP.INI中设置memory_limit,但我想这不是最好的做法…
最舒适的解决scheme是
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\ResponseHeaderBag; $response = new BinaryFileResponse($file); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT); return $response;
首先,感谢大家的回复。 我终于解决了这个没有X-SendFile(这可能是最好的做法)。 无论如何,对于那些不能让X-Sendfile的apache模块工作(共享主机),这里有一个解决scheme:
// 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服务器的任务。 最好的select是使用X-Accel-Redirect(对于Nginx)/ X-Sendfile(对于Apache)头文件下载。
下面的动作片段可以用于configurationNginx从Symfony2下载文件:
return new Response('', 200, array('X-Accel-Redirect' => $filename));
UPD1:configurationmod_xsendfile的apache代码:
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
亚历山大反应+1。
但是如果你不能使用X-Sendfile,你应该使用2.2中添加的BinaryFileResponse: 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;
从Symfony 3.2开始,您可以使用file()控制器帮助程序 ,它是创buildBinaryFileResponse
的快捷方式,如前面的答案中所述:
public function fileAction() { // send the file contents and force the browser to download it return $this->file('/path/to/some_file.pdf'); }
对于那些没有select设置标题的人:
download
属性可能会有所帮助,具体取决于您需要支持哪些浏览器:
<a href="{file url}" download>
要么
<a href="{file url}" download="{a different file name}">
这在所有旧版浏览器中都不受支持。 浏览器支持请参见此页面: