Отправка файла CSV hude напрямую в вывод браузера не работает

Так как MS Excel не умеет распознавать файлы CSV в кодировке utf-8 я попытался вручную создать такой файл, добавив префикс BOM. Но в моем случае мне нужно отправить его для открытия пользователю / браузеру, а не сохранить его на диске.
Хитрость заключается в том, что при небольшом количестве данных ~ 1-10 он работает хорошо, но при отсутствии большого количества записей он не может быть выведен в браузер (Google Chrome, FF), а печатает результат в виде HTML. Вы можете попробовать поиграть с ним по-разному count параметр в запросе GET: http://tarex.ru/index.php?r=user/pricelist&Файл = 1&кол = 100

        $limit =  $_GET['count'] ? $_GET['count'] : 10;
$filename= 'test.csv';
$out = fopen('php://output', 'w');  // open to out in browser
fwrite($out, "\xEF\xBB\xBF");  // prepend BOM
$counter=0;
foreach(Assortment::model()->findAll(  'measure_unit<>"" AND price>0' ) as $d)
{
$arr = array( $d->article2, $d->title, $d->oem,  $d->make, $d->availability , $d->getPrice(Yii::app()->user->id), $d->getDiscountOpt(Yii::app()->user->id) );
fputcsv($out, $arr, ';'); //delimiter - ;
if ($counter++ > $limit) break;
}
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
fclose($out);

Есть ли решение?

В конце концов я сделал это с Yii::app()->request->sendFile после предложения турутоции.

    $filename='test.csv';
$filepath = Yii::app()->basePath . '/../files/'. $filename;
$out      = fopen($filepath, 'w');
// writing csv ...
fwrite($out, "\xEF\xBB\xBF");  //  put BOM at the beginning of file
fputcsv($out, $arr, ';');
foreach(Assortment::model()->findAll() as $d)
{
$arr = array( $d->article2, $d->title, $d->oem,  $d->make, $d->availability);
fputcsv($out, $arr, ';'); // separator - ;
}
fclose($out);
Yii::app()->request->sendFile($filename,   @file_get_contents($filepath));

0

Решение

Я предлагаю использовать xSendFile () метод для загрузки большого файла.

$limit    =  $_GET['count'] ? $_GET['count'] : 10;
$filename = 'test.csv';
$filepath = '/path/to/xsendfile-enabled/dir/' . $filename;
$out      = fopen($filepath, 'w');
//
// write csv ...
//
fclose($out);
Yii::app()->request->xSendFile(filepath, array(
'saveName' => $filename
));
0

Другие решения

С исходным кодом проблема, вероятно, заключалась в том, что у вас есть header заявления в конце. Если затем выходные данные настолько велики, что веб-сервер сбрасывает первый блок данных в браузер, то этот браузер получает данные без этих заголовков. С этого момента уже слишком поздно отправлять заголовки.

Поэтому сначала сгенерируйте эти заголовки:

    $limit =  $_GET['count'] ? $_GET['count'] : 10;
$filename= 'test.csv';
$out = fopen('php://output', 'w');  // open to out in browser
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
fwrite($out, "\xEF\xBB\xBF");  // prepend BOM
//
// rest of output generating code comes here
//
fclose($out);
0

По вопросам рекламы [email protected]