php Symfony2 - 强制下载文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13010411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Symfony2 - Force file download
提问by Xavi
I'm trying to download a file when a user clicks on download link.
当用户单击下载链接时,我正在尝试下载文件。
In 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 is opening the dialog box to save the file, but it says the file is 0 bytes. And changing it to:
这是打开对话框以保存文件,但它说文件是 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;
I get a bunch of weird characters instead of the file download dialog box.
我得到一堆奇怪的字符而不是文件下载对话框。
Finally, switching the "setContent" line to:
最后,将“setContent”行切换为:
$response->setContent(file_get_contents($filename));
It returns a PHP error:
它返回一个 PHP 错误:
Fatal error: Allowed memory size...
致命错误:允许的内存大小...
Any clues on how to achieve this? I've done it before in PHP (wihtout MVC), but I don't know what can be missing to do it through Symfony2...
关于如何实现这一目标的任何线索?我以前在 PHP(没有 MVC)中做过,但我不知道通过 Symfony2 做它会缺少什么......
Maybe the solution is setting the memory_limit in PHP.INI, but I guess it′s not the best practice...
也许解决方案是在 PHP.INI 中设置 memory_limit,但我想这不是最佳实践......
采纳答案by Xavi
First of all, thanks to everyone for your replies. I finally solved this without X-SendFile (which is probably the best practice). Anyway, for those who can't get X-Sendfile apache module to work (shared hosting), here's a solution:
首先感谢大家的回复。我终于在没有 X-SendFile 的情况下解决了这个问题(这可能是最佳实践)。无论如何,对于那些无法让 X-Sendfile apache 模块工作(共享托管)的人,这里有一个解决方案:
// 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!
希望这可以帮助!
回答by denkweite
The most comfortable solution is
最舒服的解决办法是
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
$response = new BinaryFileResponse($file);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
return $response;
回答by lisachenko
You shouldn't use PHP for downloading files because it's a task for an Apache or Nginx server. Best option is to use X-Accel-Redirect (in case of Nginx) / X-Sendfile (in case of Apache) headers for file downloading.
您不应该使用 PHP 下载文件,因为这是 Apache 或 Nginx 服务器的任务。最好的选择是使用 X-Accel-Redirect(在 Nginx 的情况下)/X-Sendfile(在 Apache 的情况下)头文件下载。
Following action snippet can be used with configured Nginx to download files from Symfony2:
以下操作片段可与配置的 Nginx 一起使用以从 Symfony2 下载文件:
return new Response('', 200, array('X-Accel-Redirect' => $filename));
UPD1:Code for apache with configured mod_xsendfile:
UPD1:配置了 mod_xsendfile 的 apache 代码:
return new Response('', 200, array(
'X-Sendfile' => $filename,
'Content-type' => 'application/octet-stream',
'Content-Disposition' => sprintf('attachment; filename="%s"', $filename))
);
回答by Pascal
Don't know if it can help but it's application/octet-streamnot application/octect-stream
不知道它是否可以帮助但它application/octet-stream不是application/octect-stream
回答by COil
As of Symfony 3.2 you can use the file() controller helperwhich is a shortcut for creating a BinaryFileResponseas mentioned in a previous answer:
从 Symfony 3.2 开始,您可以使用file() 控制器助手,这是创建BinaryFileResponse前面答案中提到的a 的快捷方式:
public function fileAction()
{
// send the file contents and force the browser to download it
return $this->file('/path/to/some_file.pdf');
}
回答by Jaycreation
+1 for alexander response.
+1 代表亚历山大回应。
But if you can't use X-Sendfile, you should use the BinaryFileResponse added in the 2.2: http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files
但是如果你不能使用X-Sendfile,你应该使用2.2中添加的BinaryFileResponse:http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files
In my project the result is
在我的项目中,结果是
$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;
回答by Henry
For those who don't have the option of setting headers:
对于那些没有设置标题选项的人:
The downloadattribute may help depending on which browsers you need to support:
该download属性可能会有所帮助,具体取决于您需要支持的浏览器:
<a href="{file url}" download>
<a href="{file url}" download>
or
或者
<a href="{file url}" download="{a different file name}">
<a href="{file url}" download="{a different file name}">
This is not supported in all legacy browsers. See this page for browser support:
并非所有旧版浏览器都支持此功能。请参阅此页面以获取浏览器支持:

