2012-04-24 19 views
16

Estoy creando un controlador de "Descarga" usando Symfony 2, que tiene el único propósito de enviar encabezados para que pueda forzar la descarga de un archivo .csv, pero no funciona correctamente.Cómo forzar la descarga de un archivo .csv en Symfony 2, utilizando el objeto Response?

$response = new Response(); 
$response->headers->set('Content-Type', "text/csv"); 
$response->headers->set('Content-Disposition', 'attachment; filename="'.$fileName.'"'); 
$response->headers->set('Pragma', "no-cache"); 
$response->headers->set('Expires', "0"); 
$response->headers->set('Content-Transfer-Encoding', "binary"); 
$response->headers->set('Content-Length', filesize($fileName)); 
$response->prepare(); 
$response->sendHeaders(); 
$response->setContent(readfile($fileName)); 
$response->sendContent(); 

$fileName es una cadena "info.csv". Tales son mis acciones dentro de mi controlador, no hay declaración de devolución. Cuando traté de devolver el objeto Response, el contenido del archivo se mostraba en el navegador, no era mi resultado.

El problema que he encontrado es que en algunas páginas me pongo mi info.csv file, pero en anothers todo lo que consigo es un mensaje:

No webpage was found for the web address: http://mywebpage.com/download Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.

estoy completamente seguro de que el archivo existe , entonces debe haber otra cosa incorrecta. Además, routing.yml está funcionando correctamente, ya que obtengo el archivo de otras páginas que también se vinculan a esa ruta. El registro de errores de Apache no muestra nada al respecto.

¿Alguien ha forzado la descarga de un archivo .csv en Symfony 2 anteriormente? Si es así, ¿qué estoy haciendo mal?

Respuesta

33

Aquí está un ejemplo mínimo que funciona muy bien en la producción:

class MyController 
public function myAction() 

    $response = $this->render('ZaysoAreaBundle:Admin:Team/list.csv.php',$tplData); 

    $response->headers->set('Content-Type', 'text/csv'); 
    $response->headers->set('Content-Disposition', 'attachment; filename="teams.csv"'); 

    return $response; 

Puede reemplazar la llamada procesamiento con nueva respuesta y respuesta-> setContent si lo desea.

Su comentario sobre la declaración de no devolución dentro de un controlador es desconcertante. Los controladores devuelven una respuesta. Deje que el marco se encargue de enviar las cosas al navegador.

+0

$ tpldata no está definido –

7

Me doy cuenta de que esta publicación es un poco antigua y de que, curiosamente, prácticamente no hay buenos recursos sobre cómo hacer una exportación de CSV en Symfony 2 además de esta publicación en stackoverflow.

De todos modos, utilicé el ejemplo anterior para un sitio de concurso de clientes y funcionó bastante bien. Pero hoy recibí un correo electrónico y después de probarlo yo mismo, el código se había roto. Pude hacer que la descarga funcionara con una pequeña cantidad de resultados, pero la base de datos ahora exportaba más de 31,000 filas, simplemente mostraba el texto o con Chrome, básicamente no hizo nada.

Para cualquier persona que tenga problema con una gran exportación de datos, esto es lo que me manejadas para llegar al trabajo, básicamente haciendo lo CERAD sugirió como una forma alternativa:

$filename = "export_".date("Y_m_d_His").".csv"; 
    $response = $this->render('AppDefaultBundle:Default:csvfile.html.twig', array('data' => $data)); 

    $response->setStatusCode(200); 
    $response->headers->set('Content-Type', 'text/csv'); 
    $response->headers->set('Content-Description', 'Submissions Export'); 
    $response->headers->set('Content-Disposition', 'attachment; filename='.$filename); 
    $response->headers->set('Content-Transfer-Encoding', 'binary'); 
    $response->headers->set('Pragma', 'no-cache'); 
    $response->headers->set('Expires', '0'); 

    $response->prepare(); 
    $response->sendHeaders(); 
    $response->sendContent(); 

EDIT: Después de más pruebas y aumentando al máximo segundos permitidos, me di cuenta de que el código anterior estaba imprimiendo los encabezados en la parte superior, así que actualicé el código.

+1

Gracias por esto. Tuve que pasar el objeto Request $ request a través del método $ response-> prepare() para que funcione. – Acyra

5

Esto me ha funcionado para exportar CSV y JSON.

Los archivos Twig se llaman: export.csv.twig, export.json.ramita

El controlador:

class PrototypeController extends Controller { 

public function exportAction(Request $request) { 

    $data = array("data" => "test"); 

    $format = $request->getRequestFormat(); 

    if ($format == "csv") { 
     $response = $this->render('PrototypeBundle:Prototype:export.' . $format . '.twig', array('data' => $data)); 
     $filename = "export_".date("Y_m_d_His").".csv"; 
     $response->headers->set('Content-Type', 'text/csv'); 
     $response->headers->set('Content-Disposition', 'attachment; filename='.$filename); 

     return $response; 
    } else if ($format == "json") { 
     return new Response(json_encode($data)); 
    } 
} 
} 

El enrutamiento:

prototype_export: 
    pattern: /export/{_format} 
    defaults: { _controller: PrototypeBundle:Prototype:export, _format: json } 
    requirements: 
     _format: csv|json 

las ramas:

export.csv.twig (hacer lo suyo separados por comas aquí, esto es sólo una prueba)

{% for row in data %} 
{{ row }} 
{% endfor %} 

export.json.twig (los datos se envían json_encoded, este archivo está vacío)

Espero que esto ayude!

-1

Cómo sobre el uso del exportador Sonata:

use Exporter\Writer\CsvWriter; 
/** 
* @param array $orders 
*/ 
public function exportToCsv($orders) 
{ 
    $rootdir = $this->get('kernel')->getRootDir(); 
    $filename = $rootdir . '/data/orders.csv'; 
    unlink($filename); 
    $csvExport = new CsvWriter($filename); 
    $csvExport->open(); 
    foreach ($orders as $order) 
    { 
     $csvExport->write($order); 
    } 
    $csvExport->close(); 
    return; 

} 

Se estrella si el archivo ya existe, por tanto, la desvinculación de mando.

+0

¿Cómo ayuda esto al OP a descargar un archivo CSV a través del navegador? En cualquier caso, intente probar para ver si el archivo existe antes de intentar desvincularlo .... –

Cuestiones relacionadas