利用phpExcel实现远程下载文件接口

由于做后台的很多时候都会用到PHPExcel这款插件实现统计数据的导出功能,每个地方都引入这款插件和实例化当然是可以的,只是感觉有点麻烦,项目一旦多了就发现每次都要复制一份插件到新的网站去,而有些只是某个小功能需要下载而已,这样有点浪费资源!

所以我想能不能在一个地方写一次,以后每次只是调用接口即可呢?百度了一下居然没有找到,找来的都是直接输出文件流下载的。。。。

好吧,趁着周末,自己东西实现一下这种小功能。

1.首先在一个服务器上面新增一个接口,以方便其他地方调用实现下载导出文件。

(我在自己写的一个收集日志的系统上面直接加一个接口)。

2.构造数据,调整数据和定义规则。

3.测试效果

4.优化传入

5.实现远程方式

6.完成

7.总结

这里先写总结再上代码:

实现这个下功能还是遇到了一些问题,首先就是输出文件的问题,正常情况下我们是直接输出文件流的形式,然后设置header和清理缓存等,实现即时下载功能。这次发现这个文件流在curl中很难捕获,用php://input 和php://ouput 都试过,效果让人抓头!!!

直接打印curl的结果当然是文件流了,所以就要想办法保存这个文件流作为临时文件,然后远程下载即可(直接流强制转化下载失败了,所以放弃了)。

写好规范后即可实现远程curl调用下载功能,会返回一个临时文件链接,点击即可下载。

待完善:

1.设置更细节的属性,比如高度、字体属性、对齐方式等。

2.安全过滤

3.检测数据的可靠性

4.其他

效果图:


下面贴上代码:

define('LOG_URL','http://服务器地址已经马赛克/');
define('LOG_APP_ID','07授权马赛克8');
define('LOG_APP_SECRET','gF秘钥口令马赛克zJtFDsetxDxl');
 //下载数据Excel
function getExcel($file_name)
{
	$array = array(
		'mod'=>'api',
		'route'=>'data_private',
		'class'=>'down',
		'method'=>'ExcelDownload',
		'font_size'=>12,
		'app_id'=>LOG_APP_ID
	);
	$data = array(
		array('a'=>1,'b'=>'数据1','c'=>'哈哈哈','d'=>53,'e'=>'345sdf','f'=>'d','e1'=>'2522242'),
		array('a'=>3,'b'=>'数据3','c'=>'a','d'=>'adfasdfadsf','e'=>'a','f'=>'32rsdf','e1'=>'s'),
		array('a'=>4,'b'=>'数据4','c'=>'dowfj','d'=>3242,'e'=>'d','f'=>'3423','e1'=>'3'),
		array('a'=>5,'b'=>'数据5','c'=>'we','d'=>222,'e'=>'11111','f'=>'aa','e1'=>'e'),
		array('a'=>555,'b'=>'测试成功','c'=>'晚安','d'=>'待完善很多啊','e'=>'慢慢来','f'=>'好的','e1'=>'么么哒')
	);
	$data = json_encode_cn($data);
	$column =json_encode_cn(
		array([10,'标题1','a'],[12,'标题2','b'],[10,'标题3','c'],[35,'名称xx','d'],[10,'标题5','e'],[15,'标题6','f'],[15,'e1字段','e1'])
	);//[宽度,标题,字段名称]
	$array['data'] = $data;
	$array['column'] = $column;
	$array['file_name'] = $file_name;
	$array['sign'] = getSign($array);
	$file =  json_decode(sendPost(LOG_URL,$array,10),true);
	header('location:'.$file['url']);
}
getExcel('测试下载');//下载测试
	
	
	
//生成当前请求的签名
function getSign($param)
{
    $secret = LOG_APP_SECRET;//平台secret秘钥
    $str='';
    ksort($param);//key用ascii从小到大排序
    foreach ($param as $k=>$v)
    {
        //排除sign后拼接字符串
        $str .=$k.$v;
    }
    $end_str = $secret.$str.$secret;//对称拼接
    $sign = strtoupper(md5($end_str));//将字符串用MD5加密后转换大写

    return $sign;
}
/**
 * 发送post请求
 */
function sendPost($url,$post_data=array(),$timeout=10)
{
    if($url == "" || $post_data == array() || $timeout <= 0){
        return false;
    }
    //初始化
    $con = curl_init();
    //设置抓取的url
    curl_setopt($con, CURLOPT_URL, $url);
    //设置头文件的信息作为数据流输出
    curl_setopt($con, CURLOPT_HEADER, 0);
    //设置获取的信息以文件流的形式返回,而不是直接输出。
    curl_setopt($con, CURLOPT_RETURNTRANSFER, 1);
    //设置post方式提交
    curl_setopt($con, CURLOPT_POST, 1);
    //设置post数据
    curl_setopt($con, CURLOPT_POSTFIELDS, $post_data);
    //请求时间
    curl_setopt($con, CURLOPT_TIMEOUT, (int)$timeout);
    //执行命令
    curl_setopt($con, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
    curl_setopt($con, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在
    $data = curl_exec($con);
    //关闭URL请求
    curl_close($con);
    //显示获得的数据
    return $data;
}
//兼容低版本json中文乱码问题
function json_encode_cn($value)
{
    if (version_compare(PHP_VERSION,'5.4.0','<'))
    {
        $str = json_encode($value);
        $str = preg_replace_callback(
            "#\\\u([0-9a-f]{4})#i",
            function($matchs)
            {
                return iconv('UCS-2BE', 'UTF-8', pack('H4', $matchs[1]));
            },
            $str
        );
        $res = $str;
    }
    else
    {
        $res= json_encode($value, JSON_UNESCAPED_UNICODE);
    }
    return $res;
}

//下面是下载接口里面的方法,只是复制了方法出来哦,其他验证的全部忽略了!下面的保护的方法,使用请先该属性为public
 //下载excel//todo 定时清理临时文件
    protected function newExcelDownload()
    {
        //实例化Excel类
        $objPHPExcel = new PHPExcel();
        // 设置基本属性
        $objPHPExcel->getProperties()->setCreator("ctos")
            ->setLastModifiedBy("ctos")
            ->setTitle("Office 2007 XLSX Test Document")
            ->setSubject("Office 2007 XLSX Test Document")
            ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
            ->setKeywords("office 2007 openxml php")
            ->setCategory("Test result file");

        $column = json_decode($_POST['column'],true);

        if (empty($column) || !is_array($column))
        {
            return ReturnError('column非json格式,目前只支持json格式');
        }
        if (count($column[0]) < 3)
        {
            return ReturnError('column单元格式应为【宽度,列标题,字段名称】');
        }

        $data = json_decode($_POST['data'],true);

        if (empty($data) || !is_array($data))
        {
            return ReturnError('data非json格式,目前只支持json格式');
        }

        if (count($data[0]) < count($column))
        {
            return ReturnError('每个data单元数量应该不少于column的数组单元数,且有key对应column单元的‘字段名称’');
        }

        $file_name = !empty($this->data['file_name'])?trim($this->data['file_name']):'测试名称';

        $int = 65;//65字母开始位置,91是最后一个字母z的位置
        $end = $int + count($column);

        $last_col = strtoupper(chr($end-1));

        if ($end >91 )
        {
            return ReturnError('column列数不能超过26,系统按A~Z安排');
        }
        for($i= $int;$i< $end ;$i++)
        {
            $objPHPExcel->getActiveSheet()->getColumnDimension(strtoupper(chr($i)))->setWidth($column[($i-$int)][0]);//设置宽度
        }

        //设置文字大小
        $objPHPExcel->getActiveSheet()->getDefaultStyle()->getFont()->setSize(!empty($this->data['font_size'])?intval($this->data['font_size']):12);

        //设置文字对齐方式
        $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);

        //合并单元格
        $objPHPExcel->getActiveSheet()->mergeCells('A1:'.$last_col.'1');

        //设置水平居中
        for($i= $int;$i< $end ;$i++)
        {
            $objPHPExcel->getActiveSheet()->getStyle(strtoupper(chr($i)))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        }

        //设置加粗
        $objPHPExcel->getActiveSheet()->getStyle('A1:'.$last_col.'1')->getFont()->setBold(true);
        $objPHPExcel->getActiveSheet()->getStyle('A1:'.$last_col.'1')->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);
        $objPHPExcel->getActiveSheet()->getStyle('A1:'.$last_col.'1')->getBorders()->getAllBorders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);

        $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $file_name.date('Y-m-d H:i:s'));//默认首行作为名称描述

        //设置表格头名称
        for($i= $int;$i< $end ;$i++)
        {
            $objPHPExcel->setActiveSheetIndex(0)->setCellValue(strtoupper(chr($i)).'2', $column[($i-$int)][1]);//设置标题
        }

        // Miscellaneous glyphs, 编码:UTF-8

        //写入数据
        foreach ($data as $k => $item)
        {
            for($i= $int;$i< $end ;$i++)
            {
                $objPHPExcel->getActiveSheet()->setCellValue(strtoupper(chr($i)) . ($k + 3), $item[$column[$i-$int][2]]);
            }
            $objPHPExcel->getActiveSheet()->getStyle('A' . ($k + 3) . ':' .$last_col. ($k + 2))->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);
            $objPHPExcel->getActiveSheet()->getStyle('A' . ($k + 3) . ':' .$last_col. ($k + 2))->getBorders()->getAllBorders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
        }

        // 重命名表
        $objPHPExcel->getActiveSheet()->setTitle($file_name);
        // 打开Excel后默认选中的单元格
        $objPHPExcel->setActiveSheetIndex(0);
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
        $objWriter->save(ROOT_DIR.'/public/upload/file'.$_REQUEST['app_id'].'.xls');//临时文件存放位置,请及时清理
        return array('url'=>WEBURL.'upload/file'.$_REQUEST['app_id'].'.xls','code'=>0);
    }



评论/留言