PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, May 12, 2022

[FIXED] How can I export a CSV using Symfony's StreamedResponse?

 May 12, 2022     csv, php, symfony, symfony-http-foundation     No comments   

Issue

My code looks fine, I get status 200, I get the right headers, ... and yet my CSV file created will not donwload...

There is no error, so I do not understand why it's failing.

Here is my code:

namespace Rac\CaraBundle\Manager;

/* Imports */
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\StreamedResponse;

/* Local Imports */
use Rac\CaraBundle\Entity\Contact;

/**
 * Class CSV Contact Importer
 */
class CSVContactImporterManager {

    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @var EventDispatcherInterface
     */
    private $eventDispatcher;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @var ContactManager
     */
    private $contactManager;


    /**
     * @param EventDispatcherInterface $eventDispatcher
     * @param ObjectManager            $om
     * @param Contact                  $contactManager
     *
     */
    public function __construct(
    EventDispatcherInterface $eventDispatcher, ObjectManager $om, ValidatorInterface $validator, ContactManager $contactManager
    ) {
        $this->eventDispatcher = $eventDispatcher;
        $this->om = $om;
        $this->validator = $validator;
        $this->contactManager = $contactManager;
    }
    public function getExportToCSVResponse() {
        // get the service container to pass to the closure
        $contactList = $this->contactManager->findAll();
        $response = new StreamedResponse();
        $response->setCallback(
            function () use ($contactList) {
            //Import all contacts
            $handle = fopen('php://output', 'r+');
            // Add a row with the names of the columns for the CSV file
            fputcsv($handle, array('Nom', 'Prénom', 'Société', 'Position', 'Email', 'Adresse', 'Téléphone', 'Téléphone mobile'), "\t");
            $header = array();
            //print_r($contactList);
            foreach ($contactList as $row) {
                fputcsv($handle, array(
                    $row->getFirstName(),
                    $row->getLastName(),
                    $row->getCompany(),
                    $row->getPosition(),
                    $row->getEmail(),
                    $row->getAddress(),
                    $row->getPhone(),
                    $row->getMobile(),
                    ), "\t");
            }
            fclose($handle);
        }
        );
        $response->headers->set('Content-Type', 'application/force-download');
        $response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');

        return $response;
    }

And my controller :

    use Rac\CaraBundle\Entity\Contact;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use Symfony\Component\HttpFoundation\Request;
    use UCS\Bundle\RichUIBundle\Controller\BaseController;
    use UCS\Bundle\RichUIBundle\Serializer\AbstractListSerializer;
    
    /**
     * Contact BackOffice Environment Controller.
     *
     *
     *
     * @Route("/contact_environment")
     */
    class ContactEnvironmentController extends BaseController{
        /* My code here..*/
    
    
       /**
         * @Route("/export", name="contact_environment_export",options={"expose"=true})
         * @Method("GET")
         *
         * @return type
         */
        public function exort(){
            $manager = $this->get("cara.csv_contact_importer_manager");
           return $manager->getExportToCSVResponse();
    
        

}
}

My response headers:

Cache-Control:no-cache, private
Connection:close
Content-Disposition:attachment; filename="export.csv"
Content-Type:application/force-download

Solution

Here is a Response based solution as requested by the author. In this design, the csv service merely returns the csv text. The Response is generated in the controller.

The csv generator:

class ScheduleGameUtilDumpCSV
{
public function getFileExtension() { return 'csv'; }
public function getContentType()   { return 'text/csv'; }

public function dump($games)
{
    $fp = fopen('php://temp','r+');

    // Header
    $row = array(
        "Game","Date","DOW","Time","Venue","Field",
        "Group","HT Slot","AT Slot",
        "Home Team Name",'Away Team Name',
    );
    fputcsv($fp,$row);

    // Games is passed in
    foreach($games as $game)
    {
        // Date/Time
        $dt   = $game->getDtBeg();
        $dow  = $dt->format('D');
        $date = $dt->format('m/d/Y');
        $time = $dt->format('g:i A');

        // Build up row
        $row = array();
        $row[] = $game->getNum();
        $row[] = $date;
        $row[] = $dow;
        $row[] = $time;
        $row[] = $game->getVenueName();
        $row[] = $game->getFieldName();

        $row[] = $game->getGroupKey();

        $row[] = $game->getHomeTeam()->getGroupSlot();
        $row[] = $game->getAwayTeam()->getGroupSlot();
        $row[] = $game->getHomeTeam()->getName();
        $row[] = $game->getAwayTeam()->getName();

        fputcsv($fp,$row);
    }
    // Return the content
    rewind($fp);
    $csv = stream_get_contents($fp);
    fclose($fp);
    return $csv;
}

The controller:

public function renderResponse(Request $request)
{   
    // Model is passed via request
    $model = $request->attributes->get('model');
    $games = $model->loadGames();

    // The csv service
    $dumper = $this->get('csv_dumper_service');

    // Response with content
    $response = new Response($dumper->dump($games);

    // file prefix was injected
    $outFileName = $this->prefix . date('Ymd-Hi') . '.' . $dumper->getFileExtension();

    $response->headers->set('Content-Type', $dumper->getContentType());
    $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"',$outFileName));

    return $response;
}


Answered By - Cerad
Answer Checked By - Terry (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing