從前臺獲取文件:
- 前臺代碼
<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()方法獲取。
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
其中validata()是一個格式驗證,傳入參數爲最大字節size和限定的後綴ext;
/**
* 設置上傳文件的驗證規則
* @param array $rule 驗證規則
* @return $this
*/
public function validate($rule = [])
{
$this->validate = $rule;
return $this;
}
move 方法成功的話返回的是一個 \think\File 對象,你可以對上傳後的文件進行後續操作。
後續操作:
對move()方法獲取到的返回值$info可以執行:
- getExtension()獲得擴展名(後綴名)
- getSaveName()域名(路徑名)
- getFilename()文件名
好的可以獲取文件地址通過:
$url=$info->getSaveName();
注意:在文檔中查到
getSaveName 方法返回的是圖片的服務器文件地址,並不能直接用於圖片的URL地址,尤其在 windows平臺上必須做轉換才能正常顯示圖片。
所以正確的獲取路徑的方法爲:
$url=$info->getSaveName();
$file_url .= "\\" . $url;
得到的$file_url爲可用的URL地址。
則將$file_url傳入到真正的文件文件處理的方法中,這裏是import()方法。
上述過程完整代碼:
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一下全套服務:
use PHPExcel;
use PHPExcel_IOFactory;
use PHPExcel_Cell;
或者:
//引入PHPExcel
header("content-type:text/html; charset=utf-8");
vendor("phpoffice.phpexcel.Classes.PHPExcel");
就完成了引用!
二.開始處理:
1.通過實例化的PHPExcel_IOFactory對象調用createReader()方法獲得Reader對象;
$PHPReader = PHPExcel_IOFactory::createReader('Excel5'); //use excel2007 for 2007 format
2.Reader對象的load方法調用URL地址獲取到存放文件內容的PHPExcel;
$PHPExcel = $PHPReader->load($filename);
3.通過PHPExcel的getActiveSheet方法獲取sheet當前工作sheet
sheet可以存在多個,通過索引getActiveSheet(0)
$sheet = $PHPExcel->getActiveSheet(0);//獲得sheet
$highestRow = $sheet->getHighestRow(); // 取得共有數據數
4.將sheet轉化爲數組進行處理,則Excel中的內容就變成了一個二維數組,方便處理了。
$data=$sheet->toArray();
上述過程完整代碼:
/** 對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()往數據庫插數據。
最後
終於完了,有點長,寫的頭皮發麻。