如何使用 Symfony 的 StreamedResponse 导出 CSV?

dem*_*vil 5 php csv symfony symfony-http-foundation

我的代码看起来不错,我得到状态 200,我得到正确的标题,...但我创建的 CSV 文件无法下载...

\n

没有错误,所以我不明白为什么会失败。

\n

这是我的代码:

\n
namespace Rac\\CaraBundle\\Manager;\n\n/* Imports */\nuse Symfony\\Component\\PropertyAccess\\PropertyAccess;\nuse Symfony\\Component\\Validator\\ValidatorInterface;\nuse Symfony\\Component\\EventDispatcher\\EventDispatcherInterface;\nuse Doctrine\\Common\\Persistence\\ObjectManager;\nuse Symfony\\Component\\HttpFoundation\\StreamedResponse;\n\n/* Local Imports */\nuse Rac\\CaraBundle\\Entity\\Contact;\n\n/**\n * Class CSV Contact Importer\n */\nclass CSVContactImporterManager {\n\n    /**\n     * @var ObjectManager\n     */\n    private $om;\n\n    /**\n     * @var EventDispatcherInterface\n     */\n    private $eventDispatcher;\n\n    /**\n     * @var ValidatorInterface\n     */\n    private $validator;\n\n    /**\n     * @var ContactManager\n     */\n    private $contactManager;\n\n\n    /**\n     * @param EventDispatcherInterface $eventDispatcher\n     * @param ObjectManager            $om\n     * @param Contact                  $contactManager\n     *\n     */\n    public function __construct(\n    EventDispatcherInterface $eventDispatcher, ObjectManager $om, ValidatorInterface $validator, ContactManager $contactManager\n    ) {\n        $this->eventDispatcher = $eventDispatcher;\n        $this->om = $om;\n        $this->validator = $validator;\n        $this->contactManager = $contactManager;\n    }\n    public function getExportToCSVResponse() {\n        // get the service container to pass to the closure\n        $contactList = $this->contactManager->findAll();\n        $response = new StreamedResponse();\n        $response->setCallback(\n            function () use ($contactList) {\n            //Import all contacts\n            $handle = fopen('php://output', 'r+');\n            // Add a row with the names of the columns for the CSV file\n            fputcsv($handle, array('Nom', 'Pr\xc3\xa9nom', 'Soci\xc3\xa9t\xc3\xa9', 'Position', 'Email', 'Adresse', 'T\xc3\xa9l\xc3\xa9phone', 'T\xc3\xa9l\xc3\xa9phone mobile'), "\\t");\n            $header = array();\n            //print_r($contactList);\n            foreach ($contactList as $row) {\n                fputcsv($handle, array(\n                    $row->getFirstName(),\n                    $row->getLastName(),\n                    $row->getCompany(),\n                    $row->getPosition(),\n                    $row->getEmail(),\n                    $row->getAddress(),\n                    $row->getPhone(),\n                    $row->getMobile(),\n                    ), "\\t");\n            }\n            fclose($handle);\n        }\n        );\n        $response->headers->set('Content-Type', 'application/force-download');\n        $response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');\n\n        return $response;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

还有我的控制器:

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

我的回复标题:

\n
Cache-Control:no-cache, private\nConnection:close\nContent-Disposition:attachment; filename="export.csv"\nContent-Type:application/force-download\n
Run Code Online (Sandbox Code Playgroud)\n

Cer*_*rad 1

这是作者要求的基于响应的解决方案。在此设计中,csv 服务仅返回 csv 文本。响应在控制器中生成。

csv 生成器:

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;
}
Run Code Online (Sandbox Code Playgroud)

控制器:

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;
}
Run Code Online (Sandbox Code Playgroud)