1. 程式人生 > >生成器來解決大文件讀取,大數據下載

生成器來解決大文件讀取,大數據下載

als fclose 非叠代 tro class php fgetc 內存溢出 con

目錄

  • 場景
  • 下載文件
  • 讀取大文件

場景

電商平臺想要導出一年的報表數據,數據可能有百萬,平常的做法是查出所有數據放到數組或對象中,再進行excel導出,一般情況下,數據不是很多這種是沒什麽問題,但百萬級別的數據一下讀到內存中,服務器會一下崩潰,內存溢出。通常情況下也不會做這種需求,產品提出來你可以罵兩句懟回去,但老板說我就需要這個功能,你苦口婆心說幾句,但是還是要做啊。生成器可以幫我做到這些,理解概念可以看看這裏。

下載文件

  //實現下載大文件,解決內存溢出
    public function actionExport(){

        $filename =  'sun.csv'; //設置文件名
        header('Content-Type: text/csv');
        header("Content-Disposition: attachment;filename={$filename}");

        $fp = fopen('php://output', 'w');

        $sql = 'select * from "SCM_tbIOStockDtl"';

        //非叠代器實現  十萬多條數據,導出csv服務器直接崩潰,內存溢出
//        $list = Yii::$app->db->createCommand($sql)->queryAll();

        //PDO::query() 本身由叠代器實現
        $pdo = new \PDO('pgsql:host=192.168.33.30;port=5432;dbname=jump', 'postgres', '123456');
        $pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
        $list = $pdo->query($sql);

        foreach ( $list  as  $fields ) {
            fputcsv ( $fp ,  $fields );
        }

        fclose ( $fp );
    }

讀取大文件

  //讀取大文件
    public function actionRead(){

        $result = $this->readCsv(Yii::$app->basePath.'/web/file/sun.csv');

        foreach ($result as $v){
            echo "<pre>";
            var_dump( $v);
            echo "</pre>";
        }

    }

    #生成器
    function readCsv( $file ){

        $fp = fopen($file,'rb');

        while( !feof($fp) ){
            yield fgetcsv($fp);
        }

        fclose($fp);
    }

代碼細節可以看我的github片段

生成器來解決大文件讀取,大數據下載