##从前台获取文件: 前台代码
1 2 3 4 |
<input id='location' type="text" class="controls" disabled>//用来显示选择的文件 <input type="button" id="i-check" value="选择报名表" class="btn btn-sm btn-success" onclick="$('#i-file').click();" style="margin-top: -2px"> <input type="file" id='i-file' name="examfile" accept=".xlsx,.xls" onchange="$('#location').val($('#i-file').val());" style="display: none"> //隐藏的存文件的目录 |
前台获取文件为3个input框: 第一个type=“text”,用来显示获取到文件的路径; 第二个type="button"点击按钮; 第三个type="file"隐藏的获取文件的表单。 流程: 当button 触发click事件,则调用$(’#i-file’).click();触发file,当file类型的input获取到值(文件路径),则change事件将路径值显示在location。 jQuery的 .val() – 设置或返回表单字段的值。 ##后台接收文件: 获取: 通过调用request对象的file()方法获取。
1 2 3 4 5 6 7 |
if(request()->isPost()){ $file = request()->file('examfile'); if (!$file) { return $this->error('未选择任何文件','JoinController/joinMultiple'); } } |
移动(上传): 内置的上传只是上传到本地服务器,上传到远程或者第三方平台的话需要自己扩展。
1 2 3 4 5 6 7 |
// 移动到框架应用根目录/public/uploads/ 目录下 $file_url = ROOT_PATH . 'public' . DS . 'upload'; //. DS . 'excel' $config = [ 'size' => 2097152, 'ext' => 'xlsx,xls' ]; $info = $file->validate($config)->move($file_url); //2MB |
其中validata()是一个格式验证,传入参数为最大字节size和限定的后缀ext;
1 2 3 4 5 6 7 8 9 10 |
/** * 设置上传文件的验证规则 * @param array $rule 验证规则 * @return $this */ public function validate($rule = []) { $this->validate = $rule; return $this; } |
move 方法成功的话返回的是一个 \think\File 对象,你可以对上传后的文件进行后续操作, move方法如果只传入一个路径则默认会在目录下生成时间目录,且文件名为自动生成的。 例如:20180926\bbc624371e90924a8483b5421acc2e43.xlsx 时间目录20180926下的这个文件 如果不想生成时间目录,且用原始文件名,则通过传入其他参数。 原始文件名采用:move($file_url,")
1 2 3 4 5 6 7 8 |
/** * 移动文件 * @param string $path 保存路径 * @param string|bool $savename 保存的文件名 默认自动生成 * @param boolean $replace 同名文件是否覆盖 * @return false|SplFileInfo false-失败 否则返回SplFileInfo实例 */ public function move($path, $savename = true, $replace = true) |
后续操作: 对move()方法获取到的返回值$info可以执行: getExtension()获得扩展名(后缀名) getSaveName()域名 getFilename()文件名 好的可以获取文件地址通过:
1 |
$url=$info->getSaveName(); |
注意:在文档中查到 getSaveName 方法返回的是图片的服务器文件地址,并不能直接用于图片的URL地址,尤其在 windows平台上必须做转换才能正常显示图片。 所以正确的获取路径的方法为:
1 2 |
$url=$info->getSaveName(); $file_url .= "\\" . $url; |
getSaveName()得到的其实就是文件名加后缀名,要得到的file_url为可用的URL地址。则 $file_url .= "\\" . $url其中 **.=**为连接符 ,双斜杠为转义字符,本意为单斜杆。 则将**$file_url**传入到真正的文件文件处理的方法中,这里是import()方法。 上述过程完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public function upload() { if(request()->isPost()){ $file = request()->file('examfile'); if (!$file) { return $this->error('未选择任何文件','JoinController/joinMultiple'); } // 移动到框架应用根目录/public/uploads/ 目录下 $file_url = ROOT_PATH . 'public' . DS . 'upload'; //. DS . 'excel' $config = [ 'size' => 2097152, 'ext' => 'xlsx,xls' ]; $info = $file->validate($config)->move($file_url); //2MB if ($info) { $url=$info->getSaveName(); $file_url .= "\\" . $url; try{ chmod($file_url, 0777); }catch(\Exception $e){} $result = $this->import($file_url,$info->getExtension()); try{ //使用文件对象的时候没有完全关闭句柄,导致无法删除该文件。 //解决方法只需要在上传逻辑完成之后清空释放一下变量 会在public/upload下多一些空文件夹 unset($info); unlink($file_url); }catch(\Exception $e){} if (!$result) //为"" { return $this->success('导入成功','JoinController/joinMultiple'); }else { return $this->error($result,'JoinController/joinMultiple'); } } else { // 上传失败获取错误信息 return $this->error($file->getError(),'JoinController/joinMultiple'); } }else { return $this->error("非法请求",'JoinController/joinMultiple'); } } |
##处理文件: 我处理的为Excel文件,经过上述步骤将一个Excel的URL地址,和其扩展名传入了处理函数import()。 一.PHPExcel的安装和引用: 注意在处理之前必须采用使用composer安装PHPExcel。 教程 Git地址 use一下全套服务:
1 2 3 |
use PHPExcel; use PHPExcel_IOFactory; use PHPExcel_Cell; |
或者:
1 2 3 |
//引入PHPExcel header("content-type:text/html; charset=utf-8"); vendor("phpoffice.phpexcel.Classes.PHPExcel"); |
就完成了引用! 二.开始处理: 1.通过实例化的PHPExcel_IOFactory对象调用createReader()方法获得Reader对象;
1 |
$PHPReader = PHPExcel_IOFactory::createReader('Excel5'); //use excel2007 for 2007 format |
2.Reader对象的load方法调用URL地址获取到存放文件内容的PHPExcel;
1 |
$PHPExcel = $PHPReader->load($filename); |
3.通过PHPExcel的getActiveSheet方法获取sheet当前工作sheet sheet可以存在多个,通过索引getActiveSheet(0)
1 |
$sheet = $PHPExcel->getActiveSheet(0);//获得sheet |
1 |
$highestRow = $sheet->getHighestRow(); // 取得共有数据数 |
4.将sheet转化为数组进行处理,则Excel中的内容就变成了一个二维数组,方便处理了。 […]
View Details在开发过程中,经常会遇到导入导出的需求,利用phpexcel类实现起来也是比较容易的,下面,我们一步一步实现 提前将phpexcel类下载,并放在扩展目录中,如图所示 一、Excel导出 导出功能,相对复杂,复杂就复杂在设置导出的excel文件的样式以及内容如何循环赋值,而且导出之后的处理结果,一般是直接在通过浏览器下载到本地,或者发送邮件,在此,以下载到本地为例,下面是源码实现 1、首先是获取待导出的数据,这一步比较简单
1 2 3 4 5 6 7 8 9 10 |
//首先获取所有待发货的订单 $where['status'] = 2; $order_model = new OrderModel(); $res = $order_model ->with('OGModel') ->where($where) ->select()->toArray(); if(!$res) $this->error('暂无待发货的记录'); //dump($res);die; $count = count($res); |
2、设置Excel导出文件的样式以及为每个单元格赋值,这一步是导出最重要最复杂的一步,好在我都做了注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
1 //引入Excel类 2 $objPHPExcel = new \PHPExcel(); 3 // 设置excel文档的属性 4 $objPHPExcel->getProperties()->setCreator("cyf") 5 ->setLastModifiedBy("cyf Test") 6 ->setTitle("order") 7 ->setSubject("Test1") 8 ->setDescription("Test2") 9 ->setKeywords("Test3") 10 ->setCategory("Test result file"); 11 //设置excel工作表名及文件名 12 $title = '待发货订单'; 13 $excel_filename = '待发货订单_'.date('Ymd_His'); 14 // 操作第一个工作表 15 $objPHPExcel->setActiveSheetIndex(0); 16 //第一行设置内容 17 $objPHPExcel->getActiveSheet()->setCellValue('A1',$excel_filename); 18 //合并 19 $objPHPExcel->getActiveSheet()->mergeCells('A1:AC1'); 20 //设置单元格内容加粗 21 $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true); 22 //设置单元格内容水平居中 23 $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 24 //设置excel的表头 25 $sheet_title = array('订单编号','下单时间','订单金额','订单状态','支付方式','付款时间','支付单号','配送方式', 26 '收货人','联系电话','省','市','区','地址','运费','商品名称','商品货号','商品规格','商品数量','商品单价', 27 '发货单号','卖家备注','实付金额','微信/支付宝金额','余额支付','优惠金额','买家备注','物流公司','物流单号'); 28 // 设置第一行和第一行的行高 29 $objPHPExcel->getActiveSheet()->getRowDimension('1')->setRowHeight(20); 30 $objPHPExcel->getActiveSheet()->getRowDimension('2')->setRowHeight(25); 31 $letter = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 32 'Q','R','S','T', 'U','V','W','X','Y','Z','AA','AB','AC'); 33 //设置单元格 34 $objPHPExcel->getActiveSheet()->getStyle('A2:AC2')->getBorders()->getAllBorders()->setBorderStyle(\PHPExcel_Style_Border::BORDER_THIN); 35 //首先是赋值表头 36 for ($k=0;$k<29;$k++) { 37 $objPHPExcel->getActiveSheet()->setCellValue($letter[$k].'2',$sheet_title[$k]); 38 $objPHPExcel->getActiveSheet()->getStyle($letter[$k].'2')->getFont()->setSize(10)->setBold(true); 39 //设置单元格内容水平居中 40 $objPHPExcel->getActiveSheet()->getStyle($letter[$k].'2')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 41 //设置每一列的宽度 42 $objPHPExcel->getActiveSheet()->getColumnDimension($letter[$k])->setWidth(18); 43 $objPHPExcel->getActiveSheet()->getColumnDimension('P')->setWidth(30); 44 45 } 46 //开始赋值 47 for ($i=0;$i<$count;$i++) { 48 //先确定行 49 $row = $i+3;//再确定列,最顶部占一行,表头占用一行,所以加3 50 $temp = $res[$i]; 51 for ($j = 0;$j<29;$j++) { 52 //开始为每个单元格赋值 53 //初始化地址数据 54 $address_arr = []; 55 $address_arr = explode(',',$temp['address_address']); 56 //初始化商品数据 57 $product_name = $product_number = $product_attr = $product_num = $product_price = ''; 58 $cl = ','.chr(10); 59 foreach ($temp['o_g_model'] as $v) { 60 $product_name .= $v['title'].$cl; 61 $product_number .= $v['attrid'].$cl; 62 $attr = []; 63 $attr = json_decode($v['attr_name'],true); 64 if ($attr) { 65 foreach ($attr as $vv) { 66 $product_attr .= $vv.' '; 67 } 68 $product_attr .= $cl; 69 } 70 $product_num .= $v['num'].$cl; 71 $product_price .= $v['user_price'].$cl; 72 } 73 switch ($j) { 74 case 0 : 75 //订单编号 76 $cellvalue = $temp['order_num']; 77 break; 78 case 1 : 79 //下单时间 80 $cellvalue = date('Y-m-d H:i:s',$temp['addtime']); 81 break; 82 case 2 : 83 //订单金额 84 $cellvalue = $temp['price_sum']; 85 break; 86 case 3 : 87 //订单状态 88 $cellvalue = lang('ORDER_STATUS')[$temp['status']]; 89 break; 90 case 4 : 91 //支付方式 92 $cellvalue = lang('ORDER_PAY')[$temp['pay_type']]; 93 break; 94 case 5 : 95 //付款时间 96 $cellvalue = ''; 97 break; 98 case 6 : 99 //支付单号 100 $cellvalue = ''; 101 break; 102 case 7 : 103 //配送方式 104 $cellvalue = lang('POST_TYPE')[$temp['post_type']]; 105 break; 106 case 8 : 107 //收货人姓名 108 $cellvalue = $temp['address_name']; 109 break; 110 case 9 : 111 //联系电话 112 $cellvalue = $temp['address_phone']; 113 break; 114 case 10 : 115 //省 116 $cellvalue = $address_arr[0]; 117 break; 118 case 11 : 119 //市 120 $cellvalue = $address_arr[1]; 121 break; 122 case 12 : 123 //区 124 $cellvalue = $address_arr[2]; 125 break; 126 case 13 : 127 //地址 128 $cellvalue = $address_arr[3]; 129 break; 130 case 14 : 131 //运费 132 $cellvalue = $temp['p_price']; 133 break; 134 case 15 : 135 //商品名称 136 $cellvalue = $product_name; 137 break; 138 case 16 : 139 //商品货号 140 $cellvalue = $product_number; 141 break; 142 case 17 : 143 //商品规格 144 $cellvalue = $product_attr; 145 break; 146 case 18 : 147 //商品数量 148 $cellvalue = $product_num; 149 break; 150 case 19 : 151 //商品单价 152 $cellvalue = $product_price; 153 break; 154 case 20 : 155 //发货单号 156 $cellvalue = '已废弃'; 157 break; 158 case 21 : 159 //卖家备注 160 $cellvalue = ''; 161 break; 162 case 22 : 163 //实付金额 164 $cellvalue = $temp['pay_money']; 165 break; 166 case 23 : 167 //微信支付宝金额 168 $cellvalue = $temp['pay_money']; 169 break; 170 case 24 : 171 //余额支付 172 $cellvalue = $temp['static_money']; 173 break; 174 case 25 : 175 //优惠金额 176 $cellvalue = $temp['coupon']; 177 break; 178 case 26 : 179 //买家备注 180 $cellvalue = ''; 181 break; 182 case 27 : 183 //物流公司 184 $cellvalue = ''; 185 break; 186 case 28 : 187 //物流单号 188 $cellvalue = ''; 189 break; 190 } 191 //赋值 192 $objPHPExcel->getActiveSheet()->setCellValue($letter[$j].$row, $cellvalue); 193 //设置字体大小 194 $objPHPExcel->getActiveSheet()->getStyle($letter[$j].$row)->getFont()->setSize(10); 195 //设置单元格内容水平居中 196 $objPHPExcel->getActiveSheet()->getStyle($letter[$j].$row)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 197 //设置自动换行 198 if ((in_array($j,[15,16,17,18,19])) && "" != $cellvalue) { 199 $objPHPExcel->getActiveSheet()->getStyle($letter[$j].$row)->getAlignment()->setWrapText(true); // 自动换行 200 $objPHPExcel->getActiveSheet()->getStyle($letter[$j].$row)->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); // 垂直方向上中间居中 201 } 202 } 203 // 设置行高 204 $objPHPExcel->getActiveSheet()->getRowDimension($row)->setRowHeight(21); 205 } 206 unset($res); |
3、设置完之后,将生成的excel文件,通过浏览器下载到本地
1 2 3 4 5 6 7 |
1 //赋值结束,开始输出 2 $objPHPExcel->getActiveSheet()->setTitle($title); 3 header('Content-Type: application/vnd.ms-excel'); 4 header('Content-Disposition: attachment;filename="'.$excel_filename.'.xls"'); 5 header('Cache-Control: max-age=0'); 6 $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); 7 $objWriter->save('php://output'); |
4、也可以在服务器上生成excel文件,然后发送到用户邮箱
1 2 3 |
1 $filename = __ROOT__.'/upload/files/'.$excel_filename; 2 $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); 3 $objWriter->save($filename); |
二、Excel导入 相比导出,导入就简单多了,废话不多说,直接上源码 1、利用form表单获取上传的excel文件
1 2 3 4 5 6 7 |
1 $file = $_FILES['file']; 2 if ($file['error'] == 4) $this->error('请选择上传excel文件'); 3 $file_types = explode ( ".", $file['name'] ); 4 $excel_type = array('xls','csv','xlsx'); 5 if (!in_array(strtolower(end($file_types)),$excel_type)){ 6 $this->error("不是Excel文件,请重新上传"); 7 } |
2、然后,读取excel文件里面的数据,这里是边读取边处理,或者全部读取出来再处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
1 //设置获取excel对象 2 $objReader = \PHPExcel_IOFactory::createReader('Excel5');//配置成2003版本,因为office版本可以向下兼容 3 $objPHPExcel = $objReader->load($file['tmp_name'],$encode='utf-8');//$file 为解读的excel文件 4 //dump($objPHPExcel);die; 5 $sheet = $objPHPExcel->getSheet(0); 6 $highestRow = $sheet->getHighestRow(); // 取得总行数 7 $success_item = $fail_item = 0; 8 //发货 9 $order_model = new OrderModel(); 10 //开始读取数据 11 for($j=3;$j<=$highestRow;$j++) 12 { 13 $order_num = $objPHPExcel->getActiveSheet()->getCell('A'.$j)->getValue(); 14 $poster = $objPHPExcel->getActiveSheet()->getCell("AB".$j)->getValue();//物流公司 15 $logistics = $objPHPExcel->getActiveSheet()->getCell("AC".$j)->getValue();//物流单号 16 $comm = $objPHPExcel->getActiveSheet()->getCell("V".$j)->getValue();//卖家备注 17 //判断条件 18 if(!is_null($order_num) && $order_num){ 19 $res = $order_model->where('order_num',$order_num)->field('itemid,status')->find(); 20 if ($res && $res['status'] == 2) { 21 if ((!is_null($poster) && $poster) || (!is_null($logistics) && $logistics)) { 22 //更改状态 23 OrderPlanModel::addLog($res['itemid'],'确认发货',$comm); 24 $order_model->Update([ 25 'status'=>3, 26 'poster'=>$poster, 27 'logistics'=>$logistics, 28 ],['itemid'=>$res['itemid']]); 29 $success_item ++; 30 } else { 31 $fail_item ++; 32 } 33 } else { 34 $fail_item ++; 35 } 36 } else { 37 $fail_item++; 38 } 39 } 40 $this->success('成功条数:'.$success_item.',失败条数:'.$fail_item); |
多学、 多记、 多练、 from:https://www.cnblogs.com/cyfblogs/p/10115541.html
View Details在之前有写过一篇文章讲述了使用PHP快速生成excel表格文件并下载,这种方式生成Excel文件,生成速度很快,但是有缺点是: 1.单纯的生成Excel文件,生成的文件没有样式,单元格属性(填充色,宽度,高度,边框颜色…)不能自定义; 2.生成的文件虽然可以打开,但是兼容性很差,每次打开,都会报一个警告: 今天使用一个第三方的SDK(PHPExcel)实现Excel文件的导入和导出。 准备工作: 1.下载PHPExcel的SDK,下载地址:https://github.com/PHPOffice/PHPExcel。 2.将SDK解压之后的Class文件拷贝到自己的项目。 一.Excel文件读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
function excelToArray(){ require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; //加载excel文件 $filename = dirname(__FILE__).'/result.xlsx'; $objPHPExcelReader = PHPExcel_IOFactory::load($filename); $sheet = $objPHPExcelReader->getSheet(0); // 读取第一个工作表(编号从 0 开始) $highestRow = $sheet->getHighestRow(); // 取得总行数 $highestColumn = $sheet->getHighestColumn(); // 取得总列数 $arr = array('A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); // 一次读取一列 $res_arr = array(); for ($row = 2; $row <= $highestRow; $row++) { $row_arr = array(); for ($column = 0; $arr[$column] != 'F'; $column++) { $val = $sheet->getCellByColumnAndRow($column, $row)->getValue(); $row_arr[] = $val; } $res_arr[] = $row_arr; } return $res_arr; } |
或者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function excelToArray(){ require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; //加载excel文件 $filename = dirname(__FILE__).'/result.xlsx'; $objPHPExcelReader = PHPExcel_IOFactory::load($filename); $reader = $objPHPExcelReader->getWorksheetIterator(); //循环读取sheet foreach($reader as $sheet) { //读取表内容 $content = $sheet->getRowIterator(); //逐行处理 $res_arr = array(); foreach($content as $key => $items) { $rows = $items->getRowIndex(); //行 $columns = $items->getCellIterator(); //列 $row_arr = array(); //确定从哪一行开始读取 if($rows < 2){ continue; } //逐列读取 foreach($columns as $head => $cell) { //获取cell中数据 $data = $cell->getValue(); $row_arr[] = $data; } $res_arr[] = $row_arr; } } return $res_arr; } |
1 |
两种方法均可将表格数据转化为数组,然后哦再进行相关的操作就简单了。 二.Excel文件导出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
/** * 创建(导出)Excel数据表格 * @param array $list 要导出的数组格式的数据 * @param string $filename 导出的Excel表格数据表的文件名 * @param array $indexKey $list数组中与Excel表格表头$header中每个项目对应的字段的名字(key值) * @param array $startRow 第一条数据在Excel表格中起始行 * @param [bool] $excel2007 是否生成Excel2007(.xlsx)以上兼容的数据表 * 比如: $indexKey与$list数组对应关系如下: * $indexKey = array('id','username','sex','age'); * $list = array(array('id'=>1,'username'=>'YQJ','sex'=>'男','age'=>24)); */ function exportExcel($list,$filename,$indexKey,$startRow=1,$excel2007=false){ //文件引入 require_once APP_ROOT.'/Api/excel/PHPExcel.php'; require_once APP_ROOT.'/Api/excel/PHPExcel/Writer/Excel2007.php'; if(empty($filename)) $filename = time(); if( !is_array($indexKey)) return false; $header_arr = array('A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); //初始化PHPExcel() $objPHPExcel = new PHPExcel(); //设置保存版本格式 if($excel2007){ $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); $filename = $filename.'.xlsx'; }else{ $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel); $filename = $filename.'.xls'; } //接下来就是写数据到表格里面去 $objActSheet = $objPHPExcel->getActiveSheet(); //$startRow = 1; foreach ($list as $row) { foreach ($indexKey as $key => $value){ //这里是设置单元格的内容 $objActSheet->setCellValue($header_arr[$key].$startRow,$row[$value]); } $startRow++; } // 下载这个表格,在浏览器输出 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'); } |
导出文件,还可以设置模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
function exportExcel($list, $filename, $indexKey = array()) { require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel.php'; require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/Writer/Excel2007.php'; $header_arr = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); //$objPHPExcel = new PHPExcel(); //初始化PHPExcel(),不使用模板 $template = dirname(__FILE__) . '/template.xls'; //使用模板 $objPHPExcel = PHPExcel_IOFactory::load($template); //加载excel文件,设置模板 $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel); //设置保存版本格式 //接下来就是写数据到表格里面去 $objActSheet = $objPHPExcel->getActiveSheet(); $objActSheet->setCellValue('A2', "活动名称:江南极客"); $objActSheet->setCellValue('C2', "导出时间:" . date('Y-m-d H:i:s')); $i = 4; foreach ($list as $row) { foreach ($indexKey as $key => $value) { //这里是设置单元格的内容 $objActSheet->setCellValue($header_arr[$key] . $i, $row[$value]); } $i++; } // 1.保存至本地Excel表格 //$objWriter->save($filename.'.xls'); // 2.接下来当然是下载这个表格了,在浏览器输出就好了 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 . '.xls"'); header("Content-Transfer-Encoding:binary"); $objWriter->save('php://output'); } |
先弄一个excel模板 然后使用该模板导出数据 from:https://www.jianshu.com/p/f7c07763a16e
View DetailsSpring Boot 内嵌容器Undertow参数设置 配置项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多 server.undertow.io-threads=16 # 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程 # 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8 server.undertow.worker-threads=256 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可 server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region server.undertow.buffers-per-region=1024 # 是否分配的直接内存(NIO直接分配的堆外内存) server.undertow.direct-buffers=true |
来看看源代码: https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/Undertow.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ioThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2); workerThreads = ioThreads * 8; //smaller than 64mb of ram we use 512b buffers if (maxMemory < 64 * 1024 * 1024) { //use 512b buffers directBuffers = false; bufferSize = 512; } else if (maxMemory < 128 * 1024 * 1024) { //use 1k buffers directBuffers = true; bufferSize = 1024; } else { //use 16k buffers for best performance //as 16k is generally the max amount of data that can be sent in a single write() call directBuffers = true; bufferSize = 1024 * 16 - 20; //the 20 is to allow some space for protocol headers, see UNDERTOW-1209 } |
很显然,Undertow认为它的运用场景是在IO密集型的系统应用中,并且认为多核机器是一个比较容易满足的点,Undertow初始化假想应用的阻塞系数在0.8~0.9之间,所以阻塞线程数直接乘了个8,当然,如果对应用较精确的估测阻塞系数,可以配置上去。 Spring Boot内嵌容器支持Tomcat、Jetty、Undertow。为什么选择Undertow? 这里有一篇文章,时间 2017年1月26日发布的: Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers 1. Setup Spring Boot Application We will use Maven to setup a new project in Eclipse with the appropriate dependencies. We will use the starter parent for this example but the dependencies in a production application will likely be altered to streamline, optimize or customize. 1.1 Setup Spring Boot Dependencies The default embedded servlet container is Tomcat. This version of Spring Web […]
View DetailsUndertow Undertow 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器 Untertow 的特点: 轻量级:它是一个 Web 服务器,但不像传统的 Web 服务器有容器概念,它由两个核心 Jar 包组成,加载一个 Web 应用可以小于 10MB 内存 Servlet3.1 支持:它提供了对 Servlet3.1 的支持 WebSocket 支持:对 Web Socket 完全支持,用以满足 Web 应用巨大数量的客户端 嵌套性:它不需要容器,只需通过 API 即可快速搭建 Web 服务器 默认情况下 Spring Cloud 使用 Tomcat 作为内嵌 Servlet 容器,可启动一个 Tomcat 的 Spring Boot 程序与一个 Undertow 的 Spring Boot 程序,通过 VisualVM 工具进行比较,可看到 Undertow 性能优于 Tomcat 使用 Undertow 添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> |
支持 HTTP2
1 2 3 4 5 6 7 8 9 10 11 |
// 在@Configuration的类中添加@bean @Bean UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() { UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory(); // 这里也可以做其他配置 factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)); return factory; } |
配置 Undertow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Undertow 日志存放目录 server.undertow.accesslog.dir # 是否启动日志 server.undertow.accesslog.enabled=false # 日志格式 server.undertow.accesslog.pattern=common # 日志文件名前缀 server.undertow.accesslog.prefix=access_log # 日志文件名后缀 server.undertow.accesslog.suffix=log # HTTP POST请求最大的大小 server.undertow.max-http-post-size=0 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 server.undertow.io-threads=4 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 server.undertow.worker-threads=20 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分 server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region server.undertow.buffers-per-region=1024 # 是否分配的直接内存 server.undertow.direct-buffers=true |
from:https://www.jianshu.com/p/e625b8aa0e80
View Detailsflyray项目介绍 使用Spring+SpringMVC+Mybatis+dubbox 开发的一套分布式基础框架,提供支付、对账、清结算、客户管理、营销活动、库存管理、搜索模块、rocketmq做统一的消息队列中心 飞雷开源平台 cms前端工程 开发手册 开发部署文档 接口文档文档 各模块功能文档 有兴趣、想学习部署的可以加群交流 使用技术 后台 Maven构建项目 Jenkins作为持续集成 安全框架:Apache Shiro 1.3 构上采用Dubbox作为RPC框架 使用Spring+Spring MVC+MyBatisSSM框架 数据库连接池使用druid 数据库使用MySQL和Redis 采用elasticsearch实现搜索服务 采用quartz做任务调度 注册中心ZooKeeper 消息中间件RocketMQ, 在分布式事务上则采用了TCC解决订单支付方面时效性要求性高的分布式事务,可靠的消息服务则来解决如会计记录等时效性要求低的分布式事务. 前台 页面交互Vue2.x 数据可视化echarts 项目进度 组织结构 接口总线系统 对外暴露统一规范的接口,包括各个子系统的交互接口示例图: 运营中心 商户中心 开放平台 ##运行流程 ##flyray-base 项目搭建 系统环境:windows10 jdk8 eclipse tomcat8 ##搭建步骤 安装jdk1.8 安装maven 安装zookeeper 下载项目:git clone https://git.oschina.net/boleixiongdi/flyray.git eclipse导入maven项目 在群里下载缺少的dubbox包和zkclient包 解决缺少其他jar包问题,直到项目不报错 ##导入后项目结构 ##项目架构图 ##项目启动步骤 导入数据库脚本 flyray-os-各模块总的数据库.sql flyray-security-三个中心的数据库.sql 修改config工程中的resource下的dubbo、数据库配置文件 修改 flyray-rbac 下的flyray-merchant-web、flyray-open-web、flyray-operation-web中的resource\service-consumer.xml文件的dubbo IP 启动注册中心即zookeeper 启动所有的服务提供者cms、crm、pay、erp下的web工程 启动rest,rest既是cms、crm、pay、erp的服务消费者又是merchant-web、open-web、operation-web的服务提供者 最后启动merchant-web可以登录商户中心、启动operation-web可以登录运营中心、启动open-web可以看到开放平台 from:https://gitee.com/boleixiongdi/flyray
View Details今天闲来无事,学习Zookeeper,下载了Zookeeper的最新版本3.5。启动以后显示: 1 2 3 ZooKeeper JMX enabled by default Using config: /opt/zookeeper-3.5.4-beta/bin/../conf/zoo.cfg Starting zookeeper … STARTED 以为启动成功,然后连接时报错,查看后台进程,没有Zookeeper进程。 查看zookeeper的日志文件: 1 2 2018-06-29 01:36:01,142 [myid:] – ERROR [main:ZooKeeperServerMain@79] – Unable to start AdminServer, exiting abnormally org.apache.zookeeper.server.admin.AdminServer$AdminServerException: Problem starting AdminServer on address 0.0.0.0, port 8080 and command URL /commands 发现8080端口被占用,通过查阅Zookeeper3.5的官方文档,发现这是Zookeeper3.5的新特性: 这是Zookeeper AdminServer,默认使用8080端口,它的配置属性如下: 我们可以修改在zoo.cfg中修改AdminServer的端口: 1 admin.serverPort=8888 保存后,再次启动,Zookeeper启动成功。 from:https://www.cnblogs.com/boboooo/p/9242088.html
View Detailszookeeper安装教程(zookeeper3.4.8为例) zookeeper有单机、伪集群、集群三种部署方式,可根据自己对可靠性的需求选择合适的部署方式。下边是单机部署的介绍。 一、单机安装 1.1 下载 进入要下载的版本的目录,选择.tar.gz文件下载,具体需要哪个版本,这个由你自己选择 下载链接:http://archive.apache.org/dist/zookeeper/ 1.2 配置,下载解压得到如下图所示: 点击conf,把zoo_sample.cfg修改成zoo.cfg,必须是叫这个名称。然后对其进行修改。 用文本打开zoo.cfg具体修改如下: 1.3,启动zooker服务。启动命令在bin文件下的zkServer.cmd. 当看到这个2181就表示启动成功了。 对于zookeeper集群,其实也就是修改conf/zoo.cfg的dataDir的存放位置以及相应在端口号,如第一个端口号:2181,第二个3181,…依次类推。这里不做详细介绍。 检查是否安装成功方式二:运行cmd,在命令行中输入jps如下图所示,表示zookeeper安装启动成功了。 到此,单机的zookeeper布置就结束。 那么,就可以搭建dubbo了。记得在搭建前先把zookeeper启动!!! from:https://blog.csdn.net/qq_30764991/article/details/80188652
View Details症状:验证码上只有背景图没有文字 Warning: imagettftext() [function.imagettftext]: Could not find/open font in ***.php on line ** 解决方案:处理掉中文目录!! 网上搜索到的答案大多是字体文件目录不对或者相对或绝对路径方面的问题,写下这段文字给后面需要填坑的朋友。 from:https://xiumu.org/note/php-imagettftext-could-not-find-open-the-font-errors.shtml
View Detailsmaven依赖的项目报错Could not resolve dependencies for project问题 maven如果依赖本地项目 1.例如自己本地项目是模块化的 首先将报错的模块执行 clean 和package 2. 然后执行install,将上一步执行成功的jar文件安装到responsitory 3.最后执行 mvn clean install -Dmaven.test.skip=true from:https://blog.csdn.net/zgy_boke/article/details/85243453
View Details