将hude csv文件直接发送到浏览器输出不起作用

时间:2014-11-14 15:21:54

标签: php excel csv output

由于MS Excel无法recognize CSV files as of utf-8 encoding我尝试手动创建此类文件,前缀为BOM前缀。但在我的情况下,我需要发送它为用户/浏览器打开而不是将其保存在磁盘上。 诀窍在于,少量数据〜1-10可以很好地工作,但是当有大量记录输出时,它无法在浏览器(谷歌浏览器,FF)中输出,而是将结果打印为HTML。您可以尝试在GET请求中使用不同的count参数:http://tarex.ru/index.php?r=user/pricelist&file=1&count=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);   

有没有解决方案?

更新

最终我在turutosiya的建议之后用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)); 

2 个答案:

答案 0 :(得分: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
));

答案 1 :(得分:0)

使用原始代码,问题可能是您最后有header个语句。如果那时输出很大,那么Web服务器会将第一个数据块刷新到浏览器,然后该浏览器会接收没有这些标头的数据。从那一刻起发送标题为时已晚。

首先生成这些标题:

    $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);