excel导出百万的数据

<?php
namespace app\index\controller;


class Index
{
	
	public function index(){
		$this->excelout();
	}
	
	
	/**
	 * 百万级数据导出
	 */
	public function excelout(){
		//不限制执行时间,以防超时
		set_time_limit(0);
		//文件名
		$xlsName = '名字'.date('Ymd His');
		//统计总行数
		$sqlCount = 0;
	
		//表头
		$xlsCell = ['id','姓名','年龄','des'];
		//对应表头的字段
		$fields = 'id,name,age,des';
	
		//统计总行数
		$sqlCount = db('customer')->count(); 
	
		//每次取多少条
		$sqlLimit = 20000;//每次只从数据库取2000条
	
		// buffer计数器
		$cnt = 0;
	
		$fileNameArr = array();
	
		//分段执行,以免内存写满
		for ($i = 0; $i < ceil($sqlCount / $sqlLimit); $i++) {
			$fp = fopen($xlsName . '_' . $i . '.csv', 'w'); //生成临时文件
	
			$fileNameArr[] = $xlsName . '_' .  $i . '.csv';//将临时文件保存起来
	
			//第一次执行时将表头写入
			if($i == 0){
				fputcsv($fp, $xlsCell);
			}
	
			//查询出数据
			$xlsData = db('customer')->field($fields)
			->limit($i * $sqlLimit,$sqlLimit)
			->select()->toArray();
	
			foreach ($xlsData as $k=>$v) {
				$cnt++;
	
				//执行下一次循环之前清空缓冲区
				if ($sqlLimit == $cnt) {
					ob_flush();
					$cnt = 0;
				}
	
				//每行写入到临时文件
				fputcsv($fp, $v);
			}
			fclose($fp);  //每生成一个文件关闭
		}
	
		//将所有临时文件合并成一个
		foreach ($fileNameArr as $file){
			//如果是文件,提出文件内容,写入目标文件
			if(is_file($file)){
				$fileName = $file;
				//打开临时文件
				$handle1 = fopen($fileName,'r');
				//读取临时文件
				if($str = fread($handle1,filesize($fileName))){
					//关闭临时文件
					fclose($handle1);
					//打开或创建要合并成的文件,往末尾插入的方式添加内容并保存
					$handle2 = fopen($xlsName.'.csv','a+');
					//写入内容
					if(fwrite($handle2, $str)){
						//关闭合并的文件,避免浪费资源
						fclose($handle2);
					}
				}
			}
		}
	
		//将文件压缩,避免文件太大,下载慢
		$zip = new \ZipArchive();
		$filename = $xlsName . ".zip";
		$zip->open($filename, \ZipArchive::CREATE);   //打开压缩包
		$zip->addFile($xlsName.'.csv', basename($xlsName.'.csv'));   //向压缩包中添加文件
		$zip->close();  //关闭压缩包
	
		foreach ($fileNameArr as $file) {
			unlink($file); //删除csv临时文件
		}
	
		//输出压缩文件提供下载
		header("Cache-Control: max-age=0");
		header("Content-Description: File Transfer");
		header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
		header("Content-Type: application/zip"); // zip格式的
		header("Content-Transfer-Encoding: binary"); //
		header('Content-Length: ' . filesize($filename)); //
		@readfile($filename);//输出文件;
		unlink($filename); //删除压缩包临时文件
		unlink($xlsName.'.csv'); //删除合并的临时文件
	}
	
	
	
    public function test()
    {
    	$limit = 200;
    	$cnt = 0;
    	$xlsTitle = ['关注时间', '微信Openid', '微信昵称', '微信头像'];
    	
    	set_time_limit(0); 
    	$sqlCount = db('customer')->count();
    	
    	$fileName = iconv('utf-8', 'gb2312', '助力');//文件名称
    	$fileName = $fileName . date('_YmdHis');// 文件名称可根据自己情况设定
    	// 输出Excel文件头,可把user.csv换成你要的文件名
    	header('Content-Type: application/vnd.ms-excel;charset=utf-8');
    	header('Content-Disposition: attachment;filename="' . $fileName . '"');
    	header('Cache-Control: max-age=0');
    	$fileNameArr = array();
    	 
    	for ($i = 0; $i < ceil($sqlCount / $limit); $i++) { 
	        $fp = fopen($fileName . '_' . $i . '.csv', 'w'); //生成临时文件 
	        // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限 
	        $fileNameArr[] = $fileName . '_' . $i . '.csv'; // 将数据通过fputcsv写到文件句柄 
	        fputcsv($fp, $xlsTitle); 
	        $start = $i * $limit; 
	        $dataArr = db('customer')->limit($start,$limit)->select();
	       
	        foreach ($dataArr as $a) {
	            $cnt++;
	            if ($limit == $cnt) {
	                //刷新一下输出buffer,防止由于数据过多造成问题
	                ob_flush();
	                flush();
	                $cnt = 0;
	            }
	            fputcsv($fp, $a);
	        }
	        fclose($fp);  //每生成一个文件关闭
    	}
    	
   		
    	//进行多个文件压缩
    	$zip = new \ZipArchive();
    	$filename = $fileName . ".zip";
    	$zip->open($filename, $zip::CREATE);   //打开压缩包
    	foreach ($fileNameArr as $file) {
    		$zip->addFile($file, basename($file));   //向压缩包中添加文件
    	}
    	$zip->close();  //关闭压缩包
    	foreach ($fileNameArr as $file) {
    		unlink($file); //删除csv临时文件
    	}
    	
        //输出压缩文件提供下载
        header("Cache-Control: max-age=0");
        header("Content-Description: File Transfer");
        header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
        header("Content-Type: application/zip"); // zip格式的
        header("Content-Transfer-Encoding: binary"); //
        header('Content-Length: ' . filesize($filename)); //
        @readfile($filename);//输出文件;
        unlink($filename); //删除压缩包临时文件  
    } 
    
	
     
   
    
}

  

posted @ 2020-11-25 20:16  Abner3721  阅读(171)  评论(0编辑  收藏  举报