PHP 导出百万数据 CSV

最近公司项目要求把数据除了页面输出也希望有导出功能,虽然之前也做过几个导出功能,但这次数据量相对比较大,差不多一天数据就20W条,要求导7天或者30天,那么数据量就轻松破百万了甚至破千万,因此开发的过程中发现了一些大数据导出的坑,在此跟大家分享一下,互相学习,多多提提意见。

废话不多说直接上以 ThinkPHP 为例

function putCsv($head, $mark = 'user_info', $fileName = "test.csv")
{
    set_time_limit(0);
    $sqlCount = Db::table('user')->count();
    //输出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');

    $sqlLimit = 100000;//每次只从数据库取100000条以防变量缓存太大
    //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
    $limit = 100000;
    //buffer计数器
    $cnt = 0;
    $fileNameArr = array();
    //逐行取出数据,不浪费内存
    for ($i = 0; $i < ceil($sqlCount / $sqlLimit); $i++) {
    $tmpFile = '../runtime/temp/' . $mark . '_' . $i . '.csv';
      $fp = fopen($tmpFile, 'w'); //生成临时文件
      //chmod($tmpFile,777);//修改可执行权限
      $fileNameArr[] = $tmpFile;
      //将数据通过fputcsv写到文件句柄
      fputcsv($fp, $head);
      $dataArr = Db::table('user')->limit($i * $sqlLimit,$sqlLimit)->select();
      foreach ($dataArr as $a) {
          $cnt++;
          if ($limit == $cnt) {
              //刷新一下输出buffer,防止由于数据过多造成问题
              ob_flush();
              flush();
              $cnt = 0;
          }
          fputcsv($fp, $a);
      }
          fclose($fp);//每生成一个文件关闭
   }
   //进行多个文件压缩
   $zip = new ZipArchive();
   $filename =  '../runtime/temp/'.$mark . ".zip";
   $zip->open($filename, ZipArchive::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");
   header("Content-Transfer-Encoding: binary");
   header('Content-Length: ' . filesize($filename));
   @readfile($filename);//输出文件;
   unlink($filename); //删除压缩包临时文件
}
public function excelout()
{
    $array = array('ulId', 'aucSUPI', 'ucRatRest', 'ausForbidden', 'ausForbidde', 'ausAllowedArea_1',
'ausAllowedArea_2', 'ausNonAl', 'ausNonAllow', 'ausAllowN', 'ausAllow', 'ucMicoMode','aucDnn_1', 'aucDnn_2', 'aucDnn_3', 'aucLand','ulTa1','ulTa2'
        );
    $this->putCsv($array);
}

非特殊说明,本博所有文章均为博主原创。

备注:相关侵权、举报、投诉及建议等,请联系站长

添加新评论

昵称
邮箱
网站