2017-08-07 13:48:38 LCRxxoo 阅读数 363

1 文件执行时间限制 

解决

set_time_limit(0);
ini_set('max_execution_time', '0');


2内存上限

解决

ini_set("memory_limit","512M");


上面都是治标不治本的 

真的要将文件分批导出

2019-01-05 09:45:30 HZX19941018 阅读数 13217

       博主昨天在实现一个需求,因为需要用到大数据导出,所以自己动手写了一个导出方法,因为要考虑到大数据的导出,所以不能一次性读取数据库,想到了分页获取数据,写进导出缓存中,这样避免了一次性从数据库中读取大量数据而造成奔溃,思路就是分页获取数据,写进导出数组中,同时清除查询数据的缓存,这样就可以避免奔溃,下面向大家分享有关教程

       博主用的是原生方法写,跟之前另一篇博客也是很相似的,大家有兴趣也可以看看(传送门)  ,我们先来封装我们的数据库查询方法,等下会用,代码如下:

/**
 * 获取导出数据  
 * @param $getLinkClearSQl  数据库语句
 */
function getReturnData($getLinkClearSQl)
{
    $con = mysqli_connect("链接地址", "账号名", "密码", "数据库名");
    $getLinkClearingData = mysqli_query($con, $getLinkClearSQl);
    $returnData = array();
    //循环组合即将导出数据
    while ($rowData = mysqli_fetch_array($getLinkClearingData)) {
        $returnData[] = array(
            'day' => date('Y-m-d', strtotime($rowData["day"])) . ' ', 
            'num1' => $rowData["num1"],
            'num2' => $rowData["num2"],
            'num3' => $rowData["num3"],
            'num4' => $rowData["num4"],
        );
    }
    //返回已封装好的数据
    return $returnData;
}
      封装好导出数据,然后再来封装我们的私有方法,该方法能够使得导出的中文不乱码,代码如下:

function fputcsv2($handle, array $fields, $delimiter = ",", $enclosure = '"', 
    $escape_char = "\\")
{
    foreach ($fields as $k => $v) {
        $fields[$k] = iconv("UTF-8", "GB2312//IGNORE", $v);  // 这里将UTF-8转为GB2312编码
    }
    fputcsv($handle, $fields, $delimiter, $enclosure, $escape_char);
}

       接下来是我们的主体了,上面我们已经封装了两个方法,跟主体区分开,看起来会比较舒服,代码如下:

//设置时间跟最大限制
set_time_limit(0);
ini_set("memory_limit", "512M");
#设置文件名以及列名
$fileName = "导出数据";
$columnName = array('日期','字段1','字段2','字段3','字段4',); 
//设置头部
header('Content-Type: application/vnd.ms-excel;charset=utf-8');
header("Content-Disposition:filename=" . $fileName . ".csv");
// 打开PHP文件句柄,php://output 表示直接输出到浏览器
$fp = fopen('php://output', 'a');
// 将中文标题转换编码,否则乱码
foreach ($columnName as $i => $v) {
    $columnName[$i] = $v;
}
//每次获取数量
$pre_count = 100;
// 将标题名称通过fputcsv写到文件句柄
fputcsv2($fp, $columnName);
$rows = array();
//循环读取数据并导出数据
for ($t = 0; $t < intval($linkClearingNumber / $pre_count) + 1; $t++) {
    #获取页码
    $pageNumber = $t * $pre_count;
    #重构SQL
    $getLinkClearSQl = "SELECT * FROM 表名"." limit $pageNumber,$pre_count";
    #获取数据
    $export_data = getReturnData($linkData, $getLinkClearSQl);
    #循环获取存放数据
    foreach ($export_data as $item) {
        $rows = array();
        foreach ($item as $export_obj) {
            $rows[] = iconv('utf-8', 'GB18030', $export_obj);
        }
        fputcsv($fp, $rows);
    }
    // 将已经写到csv中的数据存储变量销毁,释放内存占用
    unset($export_data);
    ob_flush();
    flush();
}
exit ();

        这样我们便完成了导出上万数据而不会造成网络奔溃的方法,各位小伙伴可以尝试尝试。

        更多文章请关注微信公众号

 

2018-07-18 15:42:08 hu_feng903 阅读数 1804

开发中经常遇到,格式化导出数据库中源数据。各种框架中也有很多好用的包,直接获取数据,丢入对应的处理方法即可。
但是假如遇到导出大量的数据,特别还需要进行数据处理。一般处理大数据有如下几种解决办法:
这里写图片描述

这里主要记录下使用fputcsv方式导出数据。

public function exportData()
    {   
        set_time_limit(0);
        ini_set('memory_limit', '1024M');

        $columns = [
            '列名1', '列名2', '列名3'      //需要几列,定义好列名
        ];

        //设置好告诉浏览器要下载excel文件的headers
        header('Content-Description: File Transfer');
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment; filename="导出数据-'.date('Y-m-d', time()).'.csv"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        $fp = fopen('php://output', 'a');//打开output流
        mb_convert_variables('GBK', 'UTF-8', $columns);
        fputcsv($fp, $columns);//将数据格式化为CSV格式并写入到output流中

        //添加查询条件,获取需要的数据
        $query = Model::class()->where();

        //获取总数,分页循环处理
        $accessNum = $query->count();
        $perSize = 1000;
        $pages   = ceil($accessNum / $perSize);

        for($i = 1; $i <= $pages; $i++) {

            $db_data = $query->limit($perSize)->offset(($i-1)*$perSize)->get();

            foreach($db_data as $key => $value) {
                $rowData = [];

                //获取每列数据,转换处理成需要导出的数据
                //需要格式转换,否则会乱码
                mb_convert_variables('GBK', 'UTF-8', $rowData);
                fputcsv($fp, $rowData);
            }

            //释放变量的内存
            unset($db_data);

            //刷新输出缓冲到浏览器
            ob_flush();

            //必须同时使用 ob_flush() 和flush() 函数来刷新输出缓冲。
            flush();
        }

        fclose($fp);
        exit();
    }

这样会一边生成,一边写入下载文件,提高处理速度。
之前使用的包处理,生成一个25M的数据,要20分钟。这种方式处理需要1分多钟(也和实际处理的环境有关)。

参考内容:
https://segmentfault.com/a/1190000011663425
http://www.php.net/manual/en/function.fputcsv.php

2015-07-28 17:17:36 gaoxuaiguoyi 阅读数 3970

后台管理系统总是成百万的数据导出,使用excel导出根本不能实现,excel只支持65536,2007和2010的是1048576,所以无论哪一种都不能满足需求,csv就符合需求,不限制记录的条数,但是大量数据如果一次性处理导出,会直接导致内存溢出,脚本停止工作,所有采用分割方式导出是比较有好处的。

<?php 

		error_reporting(0);
		header ( "Content-type:application/vnd.ms-excel" );
    	        header ( "Content-Disposition:filename=" . iconv ( "UTF-8", "GBK", "topic" ) . ".csv" );	
		//连接数据库 
		$link = mysql_connect('localhost','root','root') or die('连接错误');
			//选择数据库
			mysql_select_db("bbs",$link);
			//设置字符集
			mysql_query("set names utf8");
			//查询函数
			function get_res($sql,$link){
				
				$res  = mysql_query($sql,$link);
				
				if(!$res){
					
					die("操作失败".mysql_error());
				}
				$arr=array();
				while ($row = mysql_fetch_assoc($res)) {	          
	           			$arr[]=$row;
					}
				return $arr;
			}
			//查询记录总数
			function getTotalCount(){
				
				$result = mysql_query("SELECT count(*) as count FROM medsci_edu_public_medsciedu_topic", $link);
				
				return $result['count'];
			}
    	       // 打开PHP文件句柄,php://output 表示直接输出到浏览器
    	        $fp = fopen('php://output', 'a'); 
    	        //表头
		$column_name = array('topic_id','cat_id','user_id','is_best','is_top','topic_title',
                 'topic_content','topic_img','hits','total_reply_count','created_time','last_updated_time','topic_status','last_reply_name');
    	        // 将中文标题转换编码,否则乱码
    	      foreach ($column_name as $i => $v) {  
                   $column_name[$i] = iconv('utf-8', 'gbk', $v);  
              }
        // 将标题名称通过fputcsv写到文件句柄  
              fputcsv($fp, $column_name);
    	      $pagecount = 10000;//一次读取多少条
		$totalcount = getTotalCount();//总记录数
		$sql = "select * from medsci_edu_public_medsciedu_topic";
    	   for ($i=0;$i<intval($totalcount/$pagecount)+1;$i++){
    	    $data = get_res($sql." limit ".strval($i*$pagecount).",{$pagecount}",$link);
        	foreach ( $data as $item ) {
        	    $rows = array();
        	    foreach ( $item as $v){
        	        $rows[] = iconv('utf-8', 'GBK', $v);
        	    }
    	        fputcsv($fp, $rows);
        	}
        	// 将已经写到csv中的数据存储变量销毁,释放内存占用
            unset($data);
            //刷新缓冲区
            ob_flush();
            flush();
    	}
    exit;
结果测试:

2019-06-17 16:11:57 qq_34320912 阅读数 40

PHP数据导出到Eexel表格可以有多种方式,这里简单介绍两种。

  1. 导出csv格式,简单便捷,缺点是不能设计表格样式,无法导出图片等。
            $str = "手机号,状态,报名时间,消费时间\n";
            $str = iconv('utf-8', 'gb2312', $str);
            $phone = iconv('utf-8', 'gb2312', '13333333333');
    
            $status = iconv('utf-8', 'gb2312', '已消费');
    
            $createtime = date('Y-m-d H:i:s','1560758450');
                
            $createtime = date('Y-m-d H:i:s','1560758450');
                
            $str .= $phone.",".$status.",".$createtime.",".$usertime. "\n";
            $filename = 'demo.csv';
            
            ob_end_clean();//清空输出缓存区
            header("Content-type:text/csv");
            header("Content-Disposition:attachment;filename=" . $filename);
            header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
            header('Expires:0');
            header('Pragma:public');
            echo $str;
     
  2. 使用phpexcel导出
        ini_set('display_errors','On');
        error_reporting(E_ALL);
    
        date_default_timezone_set('Asia/ShangHai');
        require_once DISCUZ_ROOT.'./source/include/PHPExcel/Classes/PHPExcel.php';
    
        //初始化PHPExcel()
        $objPHPExcel = new PHPExcel();
    
        //水平居中
        $objPHPExcel->getActiveSheet()->getStyle('A')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('B')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('C')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('D')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
    
        //垂直居中
        $objPHPExcel->getActiveSheet()->getStyle('A')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('B')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('C')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('D')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
    
        $objPHPExcel->getActiveSheet()
            ->setCellValue("A1", '会员ID')
            ->setCellValue("B1", '人民币(元)')
            ->setCellValue("C1", '状态')
            ->setCellValue("D1", '收款码');
    
        //单元格宽度
        $objPHPExcel->getActiveSheet()->getColumnDimension("B")->setWidth(11);
        $objPHPExcel->getActiveSheet()->getColumnDimension("C")->setWidth(25);
        $objPHPExcel->getActiveSheet()->getColumnDimension("D")->setWidth(25);
    
        $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
        $filename = 'demo.xlsx';
    
    
        //接下来就是写数据到表格里面去
        $objActSheet = $objPHPExcel->getActiveSheet();
        $startRow = 2;
        //这里是设置单元格的内容
        $objActSheet->setCellValue('A'.$startRow, '张三');
        $objActSheet->setCellValue('B'.$startRow, 10000);
        $objActSheet->setCellValue('C'.$startRow, '等待打款');
    
        // 图片生成
        $objDrawing[$startRow] = new \PHPExcel_Worksheet_Drawing();
        $objDrawing[$startRow]->setPath('./Uploads/201906/17/demo.jpg');//图片地址
        // 设置宽度高度
        $objDrawing[$startRow]->setHeight(150);//照片高度
        $objDrawing[$startRow]->setWidth(150); //照片宽度
        /*设置图片要插入的单元格*/
        $objDrawing[$startRow]->setCoordinates('D'.$startRow);
    
        $objDrawing[$startRow]->setWorksheet($objPHPExcel->getActiveSheet());
        // 表格高度
        $objActSheet->getRowDimension($startRow)->setRowHeight(100);
        ob_end_clean();//清空输出缓存区
        // 下载这个表格,在浏览器输出
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
        header("Content-Type:application/force-download");
        header("Content-Type:application/vnd.ms-execl");
        header("Content-Type:application/octet-stream");
        header("Content-Type:application/download");;
        header('Content-Disposition:attachment;filename='.$filename.'');
        header("Content-Transfer-Encoding:binary");
        $objWriter->save('php://output');

     

PHP导出数据库

阅读数 826

没有更多推荐了,返回首页