Загрузка CSV с помощью StreamedResponse прекращается после нескольких строк

1

У меня есть коллекция 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.

  • 1
    любая ошибка в логах? логи symfony или apache / nginx?
  • 1
    @Matteo, ничего не было добавлено в журналы, что думать об этом, довольно подозрительно. Оказывается, у меня был неправильно настроенный обработчик журнала. После исправления этого я получил Doctrine\ODM\MongoDB\DocumentNotFoundException . Видимо ссылочный документ был удален без удаления ссылки из объекта бронирования. Я думаю, что решение этой проблемы поможет решить мою проблему. :)
Показать ещё 6 комментариев
Теги:
doctrine2
doctrine-odm

2 ответа

1
Лучший ответ

Как описано в комментарии, проблема связана с недиратируемым объектом на результат от курсора. Чтобы поймать исключение и записать правильные данные, вы можете поймать исключение. Цикл необходимо переписать для исключения исключения. В качестве примера вы можете сделать цикл 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, например:

надеюсь эта помощь

0

Похоже, что это связано с ограничением вашей памяти в php.ini

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

Ударьте вверх и посмотрите, сколько строк вы получаете

  • 0
    Я отредактировал свой пост, чтобы добавить некоторую информацию о настройках памяти. У меня достаточно памяти, и весь смысл использования StreamedResponse не в том, чтобы сохранить отправленные данные в памяти.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню