Cómo enviar un archivo como respuesta desde un controlador en Symfony 3

Cómo enviar un archivo como respuesta desde un controlador en Symfony 3

Devolver un archivo (cualquier tipo de archivo) como respuesta de un controlador, es una tarea regular que se puede lograr fácilmente. Para servir un archivo estático en un controlador Symfony, le recomendamos que utilice la clase BinaryFileResponse. Esta clase representa una respuesta HTTP que entrega un archivo (extiende la clase Response).

A. Devolver archivo en el navegador

Puede devolver un archivo para que se vea en el navegador (cuando sea compatible) y devolver la clase BinaryFileResponse directamente, ya que no tiene una disposición de contenido personalizada:

<?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()
    {
        // Solo necesita proporcionar la ruta a su archivo estático
        // $filepath = 'path/to/TextFile.txt';

        // i.e Envío de un archivo desde la carpeta de recursos en / web
        // en este ejemplo, el archivo de texto.txt debe existir en el servidor
        $publicResourcesFolderPath = $this->get('kernel')->getRootDir() . '/../web/public-resources/';
        $filename = "TextFile.txt";

        // Esto debería devolver el archivo ubicado en /mySymfonyProject/web/public-resources/TextFile.txt
        // para ser visto en el navegador
        return new BinaryFileResponse($publicResourcesFolderPath.$filename);
    }
}

También puede usar el fragmento anterior si está seguro de que el archivo devuelto no se verá en el navegador y, en su lugar, se descargará . Sin embargo, si necesita descargar el archivo, le recomendamos que fuerce el tipo MIME del archivo y configure la disposición del contenido como un archivo adjunto como se muestra en el siguiente ejemplo.

B. Devolver archivo como descarga

A veces, necesita devolver un archivo para descargarlo en su controlador, por lo tanto, necesita usar la BinaryFileResponseclase, pero necesita modificar la disposición de la respuesta y agregar el tipo MIME del archivo que se descargará en los encabezados. Esto es perfecto para archivos como PDF, archivos de documentos, imágenes y videos que desea que sus clientes descarguen en lugar de leerlos en línea:

<?php

namespace myBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

// Importar clases requeridas
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser;

class DefaultController extends Controller
{
    public function indexAction()
    {
        // Solo necesita proporcionar la ruta a su archivo estático
        // $filepath = 'path/to/TextFile.txt';

        // i.e Envío de un archivo desde la carpeta de recursos en /web
        // en este ejemplo, el archivo de texto.txt debe existir en el servidor
        $publicResourcesFolderPath = $this->get('kernel')->getRootDir() . '/../web/public-resources/';
        $filename = "TextFile.txt";

        // Esto debería devolver el archivo al navegador como respuesta
        $response = new BinaryFileResponse($publicResourcesFolderPath.$filename);

        // Para generar una descarga de archivo, necesita el tipo MIME del archivo
        $mimeTypeGuesser = new FileinfoMimeTypeGuesser();

        // Establecer el tipo MIME con el adivinador o manualmente
        if($mimeTypeGuesser->isSupported()){
            // Adivina el tipo MIME del archivo según la extensión del archivo.
            $response->headers->set('Content-Type', $mimeTypeGuesser->guess($publicResourcesFolderPath.$filename));
        }else{
            // Configure el tipo MIME del archivo manualmente, en este caso para un archivo de texto es texto / plano
            $response->headers->set('Content-Type', 'text/plain');
        }

        // Establecer la disposición de contenido en línea del archivo
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $filename
        );

        return $response;
    }
}

Como puede ver, en el siguiente ejemplo adivinamos FileinfoMimeTypeGuesserel tipo MIME del archivo para descargar usando la  clase en caso de que sea compatible; de ​​lo contrario, usted debe proporcionar manualmente el tipo MIME.

El BinaryFileResponsemanejará automáticamente RangeIf-Rangecabeceras de la petición. También es compatible X-Sendfile(consulte Nginx Apache ). La entrega de un archivo estático que depende de un encabezado de aplicación se conoce como la función X-Sendfile. Para hacer uso de él, debe determinar si el X-Sendfile-Typeencabezado debe ser confiable o no y llamar trustXSendfileTypeHeader()si debe usar:

BinaryFileResponse::trustXSendfileTypeHeader();

Devolver un archivo creado dinámicamente

Al enviar un archivo creado dinámicamente, debe agregar un Content-Dispositionencabezado a su respuesta. En una respuesta HTTP normal, el encabezado de respuesta Content-Disposition es un encabezado que indica si se espera que el contenido se muestre en línea en el navegador, es decir, como una página web o como parte de una página web, o como un archivo adjunto en este caso , que se descarga y se guarda localmente. En este caso, nuestro archivo no existe en el almacenamiento del servidor sino en la memoria y las variables.

Si bien crear este encabezado para descargas de archivos básicas es fácil, usar nombres de archivo que no sean ASCII es más complicado. El resumen makeDisposition() del arduo trabajo detrás de una API simple:

<?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()
    {
        // Proporcione un nombre para su archivo con extensión
        $filename = 'TextFile.txt';
        
        // El contenido creado dinámicamente del archivo
        $fileContent = "Hello, this is the content of my File";
        
        // Devuelve una respuesta con un contenido específico
        $response = new Response($fileContent);

        // Crea la disposición del archivo
        $disposition = $response->headers->makeDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $filename
        );

        // Establecer la disposición del contenido
        $response->headers->set('Content-Disposition', $disposition);

        // Dispatch request
        return $response;
    }
}

La ejecución del controlador indexAction anterior, debería generar automáticamente una descarga para un archivo de texto con el nombre TextFiley extensión .txten su navegador. Si desea ver el archivo directamente en el navegador, puede cambiar  ResponseHeaderBag::DISPOSITION_ATTACHMENTa  ResponseHeaderBag::DISPOSITION_INLINE.

Symfony 3.2

Con el lanzamiento de Symfony 3.2, hay un nuevo método en los controladores llamado archivo que fuerza la descarga de un archivo en el navegador:

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

public function fileAction()
{
    // cargar el archivo desde el sistema de archivos
    $file = new File('/path/to/some_file.pdf');

    return $this->file($file);

    // cambiar el nombre del archivo descargado
    return $this->file($file, 'custom_name.pdf');

    // mostrar el contenido del archivo en el navegador en lugar de descargarlo
    return $this->file('invoice_3241.pdf', 'my_invoice.pdf', ResponseHeaderBag::DISPOSITION_INLINE);
}

Que te diviertas ❤️!

Esto podria interesarte

Conviertete en un programador más sociable