##从前台获取文件:
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框:
##后台接收文件:
获取:
通过调用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可以执行:
好的可以获取文件地址通过:
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中的内容就变成了一个二维数组,方便处理了。
1 |
$data=$sheet->toArray(); |
上述过程完整代码:
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 |
/** 对xlsx文件解析处理,写入数据库 * @param $filename 文件路径 * @param $ext 文件后缀 * @return string 处理结果 */ private function import($filename,$ext){ //引入PHPExcel header("content-type:text/html; charset=utf-8"); vendor("phpoffice.phpexcel.Classes.PHPExcel"); //文件导入 if ($ext == 'xls') $PHPReader = PHPExcel_IOFactory::createReader('Excel5'); //use excel2007 for 2007 format else $PHPReader = PHPExcel_IOFactory::createReader('Excel2007'); //载入excel文件 try{ $PHPExcel = $PHPReader->load($filename); }catch(\Exception $e) { return '您使用的文件可能为改变文件扩展名之后的Excel文件'; } $sheet = $PHPExcel->getActiveSheet(0);//获得sheet $highestRow = $sheet->getHighestRow(); // 取得共有数据数 $data=$sheet->toArray(); $res=$this->checkExcel($data); //结果 检查上传的Excel是否合格 if ($res) //不为"" ,即不通过 { return $res; } $hyjyzlb = new Hyjyzlb(); $yearId = $hyjyzlb->getId(); //Hyjyzlb表的id if (!$yearId) //无合适数据 { return "该时间不能报名"; } $arr['YEAR_ID'] = $yearId; //报名年份 $arr['DEPTID'] = Session::get('DEPTID','think');// 院系ID $join = new Join(); $unit = new Unit(); for($i=1;$i<$highestRow;$i++){ if(!$data[$i][0]||!$data[$i][1]||!$data[$i][2])//学号,姓名性别不全的跳过 { continue; } $arr['XH'] = $data[$i][0];//学号 $arr['XM'] = $data[$i][1]; //姓名 if ($data[$i][2]=='男') //0:男 1:女 { $arr['GENDER'] = 0; } else if ($data[$i][2]=='女'){ $arr['GENDER'] = 1; }else { continue; } for ($j=3;$j<count($data[0]);$j++) { if($data[$i][$j]=='1') { $where=[ 'NAME'=>$data[0][$j], 'GENDER' =>$arr['GENDER'] ]; $unitInfo = $unit->select($where); if (!$unitInfo) //数据库没有相关项目 { continue; }else { $arr['UNIT_ID'] = $unitInfo->ID; } $where=[ 'XH'=>$data[$i][0], 'YEAR_ID'=>$yearId, 'UNIT_ID'=>$unitInfo->ID, //运动项目id ]; $joinInfo = $join->select($where); if (!$joinInfo) //数据库没有相关报名 { $maxs = $join->getMaxNumber($yearId); $arr['NUMBER'] = sprintf("%04d\n", intval($maxs)+1); //比赛号码 $join->insertOneJoin($arr); } } } } return $res; } |
注意:
**checkExcel()**为检查表头是否和标准Excel表相同;
**insertOneJoin()**往数据库插数据。
##最后
终于完了,有点长,写的头皮发麻。
from:https://blog.csdn.net/define_LIN/article/details/81111714