使用StreamedResponse下载CSV后会在多行

时间:2015-12-09 22:48:56

标签: php symfony doctrine-orm doctrine-odm

我有一个包含几千个条目的MongoDB集合,我想将其作为CSV文件下载。

我有一些基本上做以下的代码;控制器方法使用Doctrine ODM查询数据库以获取所有记录。然后将返回的光标传送到StreamedResponse。在StreamedResponse中,我循环遍历光标并将每条记录作为CSV中的一行输出。

以下代码有效,下载文件。仅限,它包含不超过60行。它可能是什么原因导致它在此时停止流式传输,而光标计数表明有2670个结果?

// Get all available bookings
$cursor = $this
        ->get('doctrine_mongodb')
        ->getRepository('FooBundle:Booking')
        ->getQueryBuilder()
        ->getQuery()
        ->execute();

$response = new StreamedResponse(function () use ($cursor) {

    $handle = fopen('php://output', 'r+');

    $headerPrinted = false;

    // Calling $cursor->count() here returns 2670

    foreach ($cursor as $result) {
        // Transform the Booking object to a flat array.
        $data = $this->constructRow($result);

        // Print CSV header
        if (!$headerPrinted) {
            fputcsv($handle, array_keys($data), ';', '"');
            $headerPrinted = true;
        }

        // Add a line in the csv file.
        fputcsv($handle, $data, ';', '"');
    }

    fclose($handle);
});

$response->headers->set('Content-Type', 'application/force-download');
$response->headers->set('Content-Disposition', 'attachment; filename="bookings.csv"');

return $response;

据我所知,流媒体中没有代码可以在内存中累积数据。我使用Symfony 2.7,Doctrine MongoDB ODM 1.0.3和PHP 5.5.9,memory_limit为256M。

2 个答案:

答案 0 :(得分:1)

如评论中所述,问题与光标结果上的不可记录对象有关。 要捕获异常并写入正确的数据,您可以捕获异常。循环需要重写才能捕获异常。例如,您可以执行do while循环,如下所示:

do {
        try 
        {
            // this could rise an exception
            $result = $cursor->getNext()
            // Transform the Booking object to a flat array.
            $data = $this->constructRow($result);

            // Print CSV header
            if (!$headerPrinted) {
                fputcsv($handle, array_keys($data), ';', '"');
                $headerPrinted = true;
            }

            // Add a line in the csv file.
            fputcsv($handle, $data, ';', '"');
        } catch (\Exception $e) 
        {
          // do nothing and process next element
        } 
 }
while($cursor->hasNext())

我建议使用库来管理CSV写作,例如:

希望这个帮助

答案 1 :(得分:-1)

听起来与你的php.ini

中的内存限制有关

的ini_set( 'memory_limit的', '16M');

把它搞砸了,看看你得了多少行