如何从Symfony 3中的控制器发送文件作为响应

本文概述

  • 返回一个动态创建的文件
  • Symfony 3.2
从控制器返回文件(任何类型的文件)作为响应, 是可以轻松实现的常规任务。要在Symfony控制器中提供静态文件, 建议你使用BinaryFileResponse类。此类表示传递文件的HTTP响应(它扩展了Response类)。
A.在浏览器中返回文件
【如何从Symfony 3中的控制器发送文件作为响应】你可以返回要在浏览器中查看的文件(如果支持), 因为它没有自定义内容配置, 因此直接返回BinaryFileResponse类:
< ?phpnamespace myBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; // Import the BinaryFileResponseuse 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 Browserreturn new BinaryFileResponse($publicResourcesFolderPath.$filename); }}

如果你确定返回的文件不会在浏览器中查看, 而是会下载, 则也可以使用上一个代码段。但是, 如果需要下载文件, 我们建议你强制文件的模仿, 并将内容处置设置为附件, 如以下示例所示。
B.返回文件下载
有时, 你需要返回要在控制器中下载的文件, 因此需要使用BinaryFileResponse类, 但是需要修改响应的处理方式, 并在标题中添加将要下载的文件的模仿类型。这非常适合你希望客户下载而不是在线阅读的文件, 例如PDF, 文档文件, 图像和视频:
< ?phpnamespace myBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; // Import required classesuse 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 manuallyif($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背后的艰苦工作:
< ?phpnamespace myBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; // Include the Response and ResponseHeaderBaguse 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 requestreturn $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 filereturn $this-> file($file, 'custom_name.pdf'); // display the file contents in the browser instead of downloading itreturn $this-> file('invoice_3241.pdf', 'my_invoice.pdf', ResponseHeaderBag::DISPOSITION_INLINE); }

玩得开心 !

    推荐阅读