使用thinkphp開發app後端中,須要實現一個處理上傳圖片隊列的功能php
這是個上傳多圖片保存而且須要對其中一張圖片進行壓縮的功能
(使用的html5 mui框架開發app,若是直接載入原圖,app客戶端列表中圖稍微多幾張就會使得webview十分卡頓,建議在開發中,必定要對用戶上傳的圖片進行服務器端的壓縮)html
以前已經寫過一篇關入如何使用html5+的uploader上傳多張圖片到服務器的博客:
http://www.cnblogs.com/devilyouwei/p/6790255.html
而且實現了在前端進行壓縮的功能(這是第一次壓縮,有用戶手機端進行)前端
上傳到服務器後咱們還需對圖片進行處理,我這裏使用的php做爲後端語言,框架爲thinkphp5html5
須要用到thinkphp的File類和Image類
File類:前者獲取到用戶上傳的file(文件)並進行路徑和文件名的操做
File類下的方法衆多,主要有如下一些,使用以前應該先打印看一下,隨意找一個文件測試一下效果,能夠看的更加明白些:node
$file = new File(ROOT_PATH."/public/uploads/20170506/abc.jpg"); $arr = [ 'getATime' => $file->getATime(), //最後訪問時間 'getBasename' => $file->getBasename(), //獲取無路徑的basename 'getCTime' => $file->getCTime(), //獲取inode修改時間 'getExtension' => $file->getExtension(), //文件擴展名 'getFilename' => $file->getFilename(), //獲取文件名 'getGroup' => $file->getGroup(), //獲取文件組 'getInode' => $file->getInode(), //獲取文件inode 'getLinkTarget' => $file->getLinkTarget(), //獲取文件連接目標文件 'getMTime' => $file->getMTime(), //獲取最後修改時間 'getOwner' => $file->getOwner(), //文件擁有者 'getPath' => $file->getPath(), //不帶文件名的文件路徑 'getPathInfo' => $file->getPathInfo(), //上級路徑的SplFileInfo對象 'getPathname' => $file->getPathname(), //全路徑 'getPerms' => $file->getPerms(), //文件權限 'getRealPath' => $file->getRealPath(), //文件絕對路徑 'getSize' => $file->getSize(),//文件大小,單位字節 'getType' => $file->getType(),//文件類型 file dir link 'isDir' => $file->isDir(), //是不是目錄 'isFile' => $file->isFile(), //是不是文件 'isLink' => $file->isLink(), //是不是快捷連接 'isExecutable' => $file->isExecutable(), //是否可執行 'isReadable' => $file->isReadable(), //是否可讀 'isWritable' => $file->isWritable() //是否可寫 ]; print_r($arr); return false;
print_r打印到瀏覽器後:web
Array ( [getATime] => 1494041766 [getBasename] => abc.jpg [getCTime] => 1494041766 [getExtension] => jpg [getFilename] => abc.jpg [getGroup] => 0 [getInode] => 0 [getLinkTarget] => D:\wamp\www\dashen\public\uploads\20170506\abc.jpg [getMTime] => 1494041766 [getOwner] => 0 [getPath] => D:\wamp\www\dashen\/public/uploads/20170506 [getPathInfo] => SplFileInfo Object ( [pathName:SplFileInfo:private] => D:\wamp\www\dashen\/public/uploads/20170506 [fileName:SplFileInfo:private] => 20170506 ) [getPathname] => D:\wamp\www\dashen\/public/uploads/20170506/abc.jpg [getPerms] => 33206 [getRealPath] => D:\wamp\www\dashen\public\uploads\20170506\abc.jpg [getSize] => 571800 [getType] => file [isDir] => [isFile] => 1 [isLink] => [isExecutable] => [isReadable] => 1 [isWritable] => 1 )
關於如何用thinkphp5處理上傳的多張圖片文件,專門寫一個private方法來處理,最後返回處理好的圖片的路徑的數組
圖片處理包括:ajax
代碼:thinkphp
// 用戶提交疑難 public function addQues() { // 驗證登錄session if (!session("?user_info")) return ['info'=>'登陸狀態失效', 'login'=>0]; $ajax['title_id'] = input('post.title_id/d'); $ajax['content'] = input('post.content/s'); $ajax['star'] = input("post.star/s"); $ajax['reward'] = input('post.reward/s'); $ajax['message'] = input('post.message/s'); $ajax['price'] = input('post.price/f'); if($ajax['reward']!="金錢懸賞") $ajax['price'] = 0; if ($ajax['title_id'] == null || $ajax['content'] == null || $ajax['star'] == null || $ajax['reward'] == null) return ['info'=>'標題,內容,難度,懸賞方式不能爲空', 'status'=>0]; if ($ajax['title_id'] == 0 || $ajax['content'] == "" || $ajax['star'] == "" || $ajax['reward'] == "") return ['info'=>'標題,內容,難度,懸賞方式不能爲空', 'status'=>0]; // 上傳圖片 $ajax['uid'] = session("user_info")['id']; $ajax['create_time'] = time(); $ajax['update_time'] = $ajax['create_time']; $ajax['ip'] = get_client_ip(); if (request()->file() != null) { $imgs = $this->upload(); //根據imgs是否爲數組鑑定是否有上傳錯誤和超範圍 if(!is_array($imgs)) return['status'=>0,'info'=>$imgs]; $ajax = array_merge($ajax, $imgs); } $ajax['is_del'] = 0; $ajax['is_effect'] = 1; $ajax['state'] = 0; $f = db("Ques")->insert($ajax); if ($f >= 1) return ['status'=>1, 'info'=>'需求單提交成功']; else return ['status'=>0, 'info'=>'數據插入失敗']; }
此方法中,壓縮第一張圖時須要用到原圖的文件路徑,名稱等,我保存在原圖同一目錄下,在原圖前面加上「thumb_」前綴做爲區別。數據庫
調用upload方法的控制器方法(外部方法):後端
// 文件上傳轉儲(多文件) // 暫且按照UNIX路徑存儲 private function upload() { //建立的目錄名稱,日期(相對項目目錄。用於數據庫保存) $dirName = "public".DS."uploads".DS.(date('Ymd')); //建立保存目錄(絕對路徑。用於保存文件) $saveDir = ROOT_PATH.DS.$dirName; if (!file_exists($saveDir)){ mkdir($saveDir); } $files = request()->file();//取得上傳文件名 foreach ( $files as $key => $file ) { // 自動生成文件名 $info = $file->rule("get_rand")->validate(['ext'=>UPLOAD_EXT,'size'=>UPLOAD_SIZE])->move($saveDir,true,false); if ($info) { //保存到數據的值 $data[$key] = $dirName .DS. $info->getFileName(); } else { return $file->getError(); } // 壓縮第一張圖 if ($key == 'img0') { $image = Image::open($info->getRealPath()); // 保存 $thumbName = $saveDir.DS.$info->getFilename(); // 絕對路徑加上文件名 $save = $saveDir.DS."thumb_" . $info->getFilename(); $image->thumb(300, 200, Image::THUMB_CENTER)->save($save); $data['thumbnail'] = $dirName.DS.$thumbName; } } return $data; } }
注意:thinkphp批量上傳可能會出現同名文件覆蓋的問題,所以咱們從新規定了rule()方法使用的函數,在common.php寫下一個隨機生成函數,加上時間戳,這樣重複的可能性就幾乎爲0了,極不易出現重名覆蓋問題
同名覆蓋問題可能來源於上傳文件併發的轉儲,時間過短了,由於php是秒級別的UNIX時間戳,致使了產生了相同的時間戳,從而用thinkphp官方的文檔中的上傳示例代碼致使了重名覆蓋問題
//隨機生成器 function get_rand(){ $now = $_SERVER['REQUEST_TIME'];//當前系統時間,比time()多5秒 return rand().$now; }