本文概述
从控制器返回文件(任何类型的文件)作为响应, 是可以轻松实现的常规任务。要在Symfony控制器中提供静态文件, 建议你使用BinaryFileResponse类。此类表示传递文件的HTTP响应(它扩展了Response类)。
A.在浏览器中返回文件
你可以返回要在浏览器中查看的文件(如果支持), 因为它没有自定义内容配置, 因此直接返回BinaryFileResponse类:
<?php
namespace myBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// Import the BinaryFileResponse
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class DefaultController extends Controller
{
public function indexAction()
{
// You only need to provide the path to your static file
// $filepath = 'path/to/TextFile.txt';
// i.e Sending a file from the resources folder in /web
// in this example, the TextFile.txt needs to exist in the server
$publicResourcesFolderPath = $this->get('kernel')->getRootDir() . '/../web/public-resources/';
$filename = "TextFile.txt";
// This should return the file located in /mySymfonyProject/web/public-resources/TextFile.txt
// to being viewed in the Browser
return new BinaryFileResponse($publicResourcesFolderPath.$filename);
}
}
如果你确定返回的文件不会在浏览器中查看, 而是会下载, 则也可以使用上一个代码段。但是, 如果需要下载文件, 我们建议你强制文件的模仿, 并将内容处置设置为附件, 如以下示例所示。
B.返回文件下载
有时, 你需要返回要在控制器中下载的文件, 因此需要使用BinaryFileResponse类, 但是需要修改响应的处理方式, 并在标题中添加将要下载的文件的模仿类型。这非常适合你希望客户下载而不是在线阅读的文件, 例如PDF, 文档文件, 图像和视频:
<?php
namespace myBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// Import required classes
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser;
class DefaultController extends Controller
{
public function indexAction()
{
// You only need to provide the path to your static file
// $filepath = 'path/to/TextFile.txt';
// i.e Sending a file from the resources folder in /web
// in this example, the TextFile.txt needs to exist in the server
$publicResourcesFolderPath = $this->get('kernel')->getRootDir() . '/../web/public-resources/';
$filename = "TextFile.txt";
// This should return the file to the browser as response
$response = new BinaryFileResponse($publicResourcesFolderPath.$filename);
// To generate a file download, you need the mimetype of the file
$mimeTypeGuesser = new FileinfoMimeTypeGuesser();
// Set the mimetype with the guesser or manually
if($mimeTypeGuesser->isSupported()){
// Guess the mimetype of the file according to the extension of the file
$response->headers->set('Content-Type', $mimeTypeGuesser->guess($publicResourcesFolderPath.$filename));
}else{
// Set the mimetype of the file manually, in this case for a text file is text/plain
$response->headers->set('Content-Type', 'text/plain');
}
// Set content disposition inline of the file
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename
);
return $response;
}
}
如你所见, 在以下示例中, 如果支持, 则使用FileinfoMimeTypeGuesser类猜测要下载的文件的MIME类型, 否则, 你需要手动提供MIME类型。
BinaryFileResponse将自动处理请求中的Range和If-Range标头。它还支持X-Sendfile(有关Nginx和Apache, 请参见)。取决于应用程序标头的静态文件的传递称为X-Sendfile功能。要使用它, 你需要确定是否应该信任X-Sendfile-Type标头, 如果使用以下方法, 请调用trustXSendfileTypeHeader():
BinaryFileResponse::trustXSendfileTypeHeader();
返回一个动态创建的文件
发送动态创建的文件时, 必须将Content-Disposition标头添加到响应中。在常规HTTP响应中, Content-Disposition响应标头是一个标头, 用于指示内容是否应在浏览器中内联显示, 即作为网页还是作为网页的一部分, 或作为此附件中的附件情况下, 将其下载并保存在本地。在这种情况下, 我们的文件不存在于服务器的存储中, 而是存在于内存和变量中。
虽然为基本文件下载创建此标头很容易, 但使用非ASCII文件名则涉及更多。 makeDisposition()抽象了简单API背后的艰苦工作:
<?php
namespace myBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// Include the Response and ResponseHeaderBag
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
class DefaultController extends Controller
{
public function indexAction()
{
// Provide a name for your file with extension
$filename = 'TextFile.txt';
// The dinamically created content of the file
$fileContent = "Hello, this is the content of my File";
// Return a response with a specific content
$response = new Response($fileContent);
// Create the disposition of the file
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename
);
// Set the content disposition
$response->headers->set('Content-Disposition', $disposition);
// Dispatch request
return $response;
}
}
前一个控制器的indexAction的执行应在浏览器中自动生成一个文本文件的下载, 文件名为TextFile, 扩展名为.txt。如果要直接在浏览器中查看文件, 可以将ResponseHeaderBag :: DISPOSITION_ATTACHMENT更改为ResponseHeaderBag :: DISPOSITION_INLINE。
Symfony 3.2
随着Symfony 3.2的发布, 控制器上有一个新方法, 即file, 它强制在浏览器中下载文件:
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
public function fileAction()
{
// load the file from the filesystem
$file = new File('/path/to/some_file.pdf');
return $this->file($file);
// rename the downloaded file
return $this->file($file, 'custom_name.pdf');
// display the file contents in the browser instead of downloading it
return $this->file('invoice_3241.pdf', 'my_invoice.pdf', ResponseHeaderBag::DISPOSITION_INLINE);
}
玩得开心 !
评论前必须登录!
注册