文件下载是实际项目中经常用的一个接口,不同于图片下载客户端自己保存就可以了,需要开放对应的接口。同时,一般会结合PHPExcel导出EXCEL表格。随着 PhpSpreadsheet的更新,三种方式一并在此总结下。
1.普通文件下载
//文件下载, readfile实现
$fileinfo = pathinfo($filename['path']);
header('Content-type: application/x-'.$fileinfo['extension']);
header('Content-Disposition: attachment; filename='.$fileinfo['basename']);
header('Content-Length: '.$filename['size']);
readfile(ROOT_PATH ."public" . DS . $filename['path']);
exit();
2.1文件下载+PHPExcel(头铁版)
缺点:表格设置需要代码层实现,较为复杂
优点:仅需要在代码层更改
//河长信息导出
public function getRiverOwnerDown(){
$condition = [];
RequestFunc::conditionAdd($condition, $this->get, ["pageNo", "pageSize", "river_type", "river_style", 'town_id', 'village_id','role_ids','searchWord','level_id']);
$orderBy['groupBy'] =['ro.user_id'];
RequestFunc::buildOrderBy($orderBy,$this->get);
$expTitle = "河长信息";
$expCellName = ['河长姓名','河长级别','河道名称','工作单位','所属村镇','办公电话','联系方式','任职详情'];
//只查看河长数据
$condition['check_brother'] = 1;
//非市级河长办只能看到本镇的数据
//$this->admin['town_id'] =0;
if($this->admin['town_id'] !== 0){
$condition['town_id'] = $this->admin['town_id'];
}
$fields = ["au.user_name", 'rl.level_name', "r.river_name", "au.department", "CONCAT(au.town,au.village) as address", 'au.department_tel', 'au.mobile','au.position'];
$expTableData = $this->dataDao->river_riverOwner_town_village($condition, $fields)->select();
foreach ($expTableData as $key => $value) {
$expTableData[$key] = array_values($value);
}
ExcelFunc::phpExcelOutput($expTitle,$expCellName,$expTableData);
}
2.2文件下载+PHPExcel(结合模板下载方式)
优点:表格设置可直接修改对应模板xls
缺点:需要单独上传空模板xls
/*
* 河长数据导出
*/
public function userExport()
{
$excel = $_SERVER['DOCUMENT_ROOT'] . "/../application/common/json/user.xlsx";
$link = [
"B" => "user_name",//河长姓名
"C" => "level_name",//河长级别
"D" => "river_name",//河道名称
"E" => "river_style",//河道类型
"F" => "river_type",//河道等级
"G" => "department",//工作单位
"H" => "town",//所属镇村
"I" => "mobile",//联系电话
"J" => "department_tel",//办公电话
];
$userService = new UserService();
CommonFunc::arrEmptyReplace($this->get,['level_id'],'1,2,4,5,8,9,10,11,12,13,14,15,16,17,18,19,20');
if(!empty($this->get['river_type']))
{
switch($this->get['river_type']){
//市级河道
case 1:
$this->get['level_id'] = array_intersect([4,14,5,15,8,16,10,18],explode(",",$this->get['level_id']));
break;
//镇级河道
case 2:
$this->get['level_id'] = array_intersect([9,17,11,19],explode(",",$this->get['level_id']));
break;
//村级河道
case 3:
$this->get['level_id'] = array_intersect([13,20],explode(",",$this->get['level_id']));
break;
//市级河道XX段
case 4:
$this->get['level_id'] = array_intersect([4,14,5,15,8,16,10,18],explode(",",$this->get['level_id']));
break;
default:
break;
}
}
$list = $userService->userList($this->get)["list"];
foreach ($list as $k => &$v) {
//导出河道——river_type字段特别显示
if ($v['river_style'] == 0) {
$river_type_exchange = ["1" => "市级河道", "2" => "镇级河道", "3" => "村级河道"];
}else if ($v['river_style'] ==1) {
$river_type_exchange = ["1" => "市级湖泊", "2" => "镇级湖泊", "3" => "村级湖泊"];
}else{
$river_type_exchange = ["1" => "水库", "2" => "水库", "3" => "水库"];
}
CommonFunc::arrReplace($v, [
"river_type" => $river_type_exchange,
"river_style" => ["0" => "河道", "1" => "湖泊", "2" => "水库"],
]);
}
$title = "河长信息表";
ExcelFunc::outPutByLoad($excel, $link, $list, $title);
}
下面附上以上两种方法用到的PHPExcel公共函数
需要用composer安装——composer require phpoffice/phpexcel
疑问:这里没用引入也能直接实例化,说是什么工厂类之类的,反正就是可以吧,有点醉
getProperties()->setCreator("php")//设置文档属性作者
->setLastModifiedBy("php")//设置最后修改人
->setTitle("Microsoft Office Excel Document")//设置文档属性标题
->setSubject("php")//设置文档属性文档主题
->setDescription("php")//设置文档属性备注
->setKeywords("php")//设置文档属性关键字
->setCategory("php");//设置文档属性类别
//设置表的名称
$objPHPExcel->getActiveSheet()->setTitle($expTitle);
if (!empty($style)) {
if (!empty($style['width'])) {
foreach ($style['width'] as $k => $v) {
$objPHPExcel->getActiveSheet()->getColumnDimension($k)->setWidth($v);
}
}
if (!empty($style['height'])) {
foreach ($style['height'] as $k => $v) {
$objPHPExcel->getActiveSheet()->getRowDimension($k)->setRowHeight($v);
}
}
//固定表头
if (!empty($style['freezePane'])) {
$objPHPExcel->getActiveSheet()->freezePane($style['freezePane']);
}
}
//自动换行、左右垂直居中
$objPHPExcel->getDefaultStyle()->getAlignment()->setWrapText(true);
$objPHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
$objPHPExcel->getDefaultStyle()->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
for ($i = 0; $i < $cellNum; $i++) {
//遍历设置单元格的值 设置列名
$objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i] . '1', $expCellName[$i]);
if (!empty($expCellName[$i]['color'])) {
$objPHPExcel->getActiveSheet()->getStyle($cellName[$i] . '1')->getFont()->getColor()->setARGB($expCellName[$i]['color']);
}
}
//让总循环次数小于数据条数
for ($i = 0; $i < $dataNum; $i++) {
//让每列的数据数小于列数
for ($j = 0; $j < $cellNum; $j++) {
//设置单元格的值
$objPHPExcel->getActiveSheet()->setCellValue($cellName[$j] . ($i + 2), ' '.$expTableData[$i][$j]);
}
}
header('pragma:public');
header('Content-type:application/vnd.ms-excel;charset=utf-8;name="' . $xlsTitle . '.xls"');
header("Content-Disposition:attachment;filename=$expTitle.xls");//attachment新窗口打印inline本窗口打印
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
}
/*
* 加载表格,填充数据
*/
public static function outPutByLoad($excel, $link, $list, $title)
{
$Reader = new \PHPExcel_Reader_Excel2007();
$PHPExcel = $Reader->load($excel);
foreach($list as $k => $v){
$PHPExcel->getActiveSheet()->setCellValue("A".($k+2), $k+1);
foreach($link as $k1 => $v1){
$key = $k1.($k+2);
$PHPExcel->getActiveSheet()->setCellValue($key, $v[$v1]);
}
}
header('pragma:public');
$xlsTitle = 100;
header('Content-type:application/vnd.ms-excel;charset=utf-8;name="'.$xlsTitle.'.xls"');
header("Content-Disposition:attachment;filename={$title}.xls");//attachment新窗口打印inline本窗口打印
$objWriter = \PHPExcel_IOFactory::createWriter($PHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
}
}
3.文件导入+PhpSpreadsheet
优点:官方推荐的新方法,导出速度更快,量更大
缺点:英文文档读的一脸懵逼,相关demo不多,引入就难了半天
官方手册:phpspreadsheet手册
大神指南:使用PhpSpreadsheet读取和写入Excel
load($inputFileName);
$list = $spreadsheet->getActiveSheet()->toArray();
//获取json
$json = file_get_contents(dirname(__FILE__) .'../../../common/Json/'.$name.'.json');
$json = json_decode($json, true);
//将表中的数据重组成数据库录入的数组
$data = $this->buildArray($list,$json);//halt($data);
$report = db('company_month_report')->where('date_time',$data[0]['date_time'])->column('id');//halt($report);
foreach ($data as $key => $value) {
if(in_array($value['id'], $report)){
$result = db('company_month_report')
->where('date_time',$value['date_time'])
->where('id',$value['id'])
->update($value);
}else{
$result = db('company_month_report')->insert($value);
}
}
// halt(session('user_auth.is_government'));
//该部门数据导入成功后,向cxly_department_work表中写入数据,方便定时任务提醒
$result =db('department_work')->insert([
'date_time'=>$data[0]['date_time'],
'department_id'=>session('user_auth.is_government')
]);
if($result){
return $this->success("导入成功!", url('enterprise/index'));
}
}
}