摘要:開發(fā)一個通用文件上傳包,發(fā)布到,并在中測試。一創(chuàng)建一個名新倉庫,并克隆至本地。九項目中使用我以中使用舉例其他本文通用上傳類由中修改本文首發(fā)琯琯博客,可前往瀏覽更多文章。
開發(fā)一個 composer 通用文件上傳包,發(fā)布到 Packagist,并在 Laravel 中測試。
一、GitHub 創(chuàng)建一個名 uploadfile 新倉庫,并克隆至本地。$ git clone git@github.com:guanguans/uploadfile.git $ cd uploadfile二、初始化項目,生成composer.json文件 2.1 步驟
yzm@Alert MINGW64 /i/phpstudy/WWW/uploadfile $ composer init Welcome to the Composer config generator This command will guide you through creating your composer.json config. Package name (2.2 步驟解釋/ ) [yzm/try-make-package]: guanguans/uploadfile Description []: 一個通用文件上傳包 Author [guanguans <53222411@qq.com>, n to skip]: guanguans Minimum Stability []: dev Package Type (e.g. library, project, metapackage, composer-plugin) []: l ibrary License []: MIT Define your dependencies. Would you like to define your dependencies (require) interactively [yes] ? yes Search for a package: php Enter the version constraint to require (or leave blank to use the lates t version): >=5.4.0 Search for a package: Would you like to define your dev dependencies (require-dev) interactive ly [yes]? yes Search for a package: php Enter the version constraint to require (or leave blank to use the lates t version): >=5.4.0 Search for a package: { "name": "guanguans/uploadfile", "description": "一個通用文件上傳包", "type": "library", "require": { "php": ">=5.4" }, "require-dev": { "php": ">=5.4" }, "license": "MIT", "authors": [ { "name": "guanguans", "email": "yzmguanguan@gmail.com" } ], "minimum-stability": "dev" } Do you confirm generation [yes]? yes
yzm@Alert MINGW64 /i/phpstudy/WWW/uploadfile $ composer init Welcome to the Composer config generator This command will guide you through creating your composer.json config. // 1. 輸入項目命名空間 // 注意三、添加自動加載/ 必須要符合 [a-z0-9_.-]+/[a-z0-9_.-]+ Package name ( / ) [dell/htdocs]: yourname/projectname // 2. 項目描述 Description []: 這是一個測試 // 3. 輸入作者信息,可以直接回車 Author [guanguans <53222411@qq.com>, n to skip]: // 4. 輸入最低穩(wěn)定版本,stable, RC, beta, alpha, dev Minimum Stability []: dev // 5. 輸入項目類型, Package Type (e.g. library, project, metapackage, composer-plugin) []: library // 6. 輸入授權(quán)類型 License []: > Define your dependencies. // 7. 輸入依賴信息 Would you like to define your dependencies (require) interactively [yes]? // 如果需要依賴,則輸入要安裝的依賴 Search for a package: php // 輸入版本號 Enter the version constraint to require (or leave blank to use the latest version): >=5.4.0 // 如需多個,則重復(fù)以上兩個步驟 // 8. 是否需要require-dev, Would you like to define your dev dependencies (require-dev) interactively [yes]? // 操作同上 { "name": "guanguans/uploadfile", "description": "一個通用文件上傳包", "type": "library", "require": { "php": ">=5.4" }, "require-dev": { "php": ">=5.4" }, "license": "MIT", "authors": [ { "name": "guanguans", "email": "yzmguanguan@gmail.com" } ], "minimum-stability": "dev" } // 9. 是否生成composer.json Do you confirm generation [yes]? yes
在上一步生成的composer.json中追加
"autoload": { "psr-4": { "Guanguans": "src/" } }四、構(gòu)建項目 4.1 新建uploadfile/src/UploadFile.php
├─uploadfile │ ├─src │ │ ├─UploadFile.php │ └─composer.json
*/ namespace Guanguans; // 注意命名空間與 composer.json 中的一致 class UploadFile { private $config = [ "maxSize" => -1, // 上傳文件的最大值 "supportMulti" => true, // 是否支持多文件上傳 "allowExts" => [], // 允許上傳的文件后綴 留空不作后綴檢查 "allowTypes" => [], // 允許上傳的文件類型 留空不做檢查 "thumb" => false, // 使用對上傳圖片進(jìn)行縮略圖處理 "imageClassPath" => "ORG.Util.Image", // 圖庫類包路徑 "thumbMaxWidth" => "",// 縮略圖最大寬度 "thumbMaxHeight" => "",// 縮略圖最大高度 "thumbPrefix" => "thumb_",// 縮略圖前綴 "thumbSuffix" => "", "thumbPath" => "",// 縮略圖保存路徑 "thumbFile" => "",// 縮略圖文件名 "thumbExt" => "",// 縮略圖擴(kuò)展名 "thumbRemoveOrigin" => false,// 是否移除原圖 "thumbType" => 1, // 縮略圖生成方式 1 按設(shè)置大小截取 0 按原圖等比例縮略 "zipImages" => false,// 壓縮圖片文件上傳 "autoSub" => false,// 啟用子目錄保存文件 "subType" => "hash",// 子目錄創(chuàng)建方式 可以使用hash date custom "subDir" => "", // 子目錄名稱 subType為custom方式后有效 "dateFormat" => "Ymd", "hashLevel" => 1, // hash的目錄層次 "savePath" => "",// 上傳文件保存路徑 "autoCheck" => true, // 是否自動檢查附件 "uploadReplace" => false,// 存在同名是否覆蓋 "saveRule" => "uniqid",// 上傳文件命名規(guī)則 "hashType" => "md5_file",// 上傳文件Hash規(guī)則函數(shù)名 ]; // 錯誤信息 private $error = ""; // 上傳成功的文件信息 private $uploadFileInfo ; public function __get($name){ if(isset($this->config[$name])) { return $this->config[$name]; } return null; } public function __set($name,$value){ if(isset($this->config[$name])) { $this->config[$name] = $value; } } public function __isset($name){ return isset($this->config[$name]); } /** * 架構(gòu)函數(shù) * @access public * @param array $config 上傳參數(shù) */ public function __construct($config=[]) { if(is_array($config)) { $this->config = array_merge($this->config,$config); } } /** * 上傳一個文件 * @access public * @param mixed $name 數(shù)據(jù) * @param string $value 數(shù)據(jù)表名 * @return string */ private function save($file) { $filename = $file["savepath"].$file["savename"]; if(!$this->uploadReplace && is_file($filename)) { // 不覆蓋同名文件 $this->error = "文件已經(jīng)存在!".$filename; return false; } // 如果是圖像文件 檢測文件格式 if( in_array(strtolower($file["extension"]), ["gif","jpg","jpeg","bmp","png","swf"])) { $info = getimagesize($file["tmp_name"]); if(false === $info || ("gif" == strtolower($file["extension"]) && empty($info["bits"]))){ $this->error = "非法圖像文件"; return false; } } if(!move_uploaded_file($file["tmp_name"], $this->autoCharset($filename,"utf-8","gbk"))) { $this->error = "文件上傳保存錯誤!"; return false; } if($this->thumb && in_array(strtolower($file["extension"]), ["gif","jpg","jpeg","bmp","png"])) { $image = getimagesize($filename); if(false !== $image) { //是圖像文件生成縮略圖 $thumbWidth = explode(",",$this->thumbMaxWidth); $thumbHeight = explode(",",$this->thumbMaxHeight); $thumbPrefix = explode(",",$this->thumbPrefix); $thumbSuffix = explode(",",$this->thumbSuffix); $thumbFile = explode(",",$this->thumbFile); $thumbPath = $this->thumbPath?$this->thumbPath:dirname($filename)."/"; $thumbExt = $this->thumbExt ? $this->thumbExt : $file["extension"]; //自定義縮略圖擴(kuò)展名 // 生成圖像縮略圖 import($this->imageClassPath); for($i=0,$len=count($thumbWidth); $i<$len; $i++) { if(!empty($thumbFile[$i])) { $thumbname = $thumbFile[$i]; }else{ $prefix = isset($thumbPrefix[$i])?$thumbPrefix[$i]:$thumbPrefix[0]; $suffix = isset($thumbSuffix[$i])?$thumbSuffix[$i]:$thumbSuffix[0]; $thumbname = $prefix.basename($filename,".".$file["extension"]).$suffix; } if(1 == $this->thumbType){ Image::thumb2($filename,$thumbPath.$thumbname.".".$thumbExt,"",$thumbWidth[$i],$thumbHeight[$i],true); }else{ Image::thumb($filename,$thumbPath.$thumbname.".".$thumbExt,"",$thumbWidth[$i],$thumbHeight[$i],true); } } if($this->thumbRemoveOrigin) { // 生成縮略圖之后刪除原圖 unlink($filename); } } } if($this->zipImags) { // TODO 對圖片壓縮包在線解壓 } return true; } /** * 上傳所有文件 * @access public * @param string $savePath 上傳文件保存路徑 * @return string */ public function upload($savePath ="") { //如果不指定保存文件名,則由系統(tǒng)默認(rèn) if(empty($savePath)) $savePath = $this->savePath; // 檢查上傳目錄 if(!is_dir($savePath)) { // 檢查目錄是否編碼后的 if(is_dir(base64_decode($savePath))) { $savePath = base64_decode($savePath); }else{ // 嘗試創(chuàng)建目錄 if(!mkdir($savePath)){ $this->error = "上傳目錄".$savePath."不存在"; return false; } } }else { if(!is_writeable($savePath)) { $this->error = "上傳目錄".$savePath."不可寫"; return false; } } $fileInfo = []; $isUpload = false; // 獲取上傳的文件信息 // 對$_FILES數(shù)組信息處理 $files = $this->dealFiles($_FILES); foreach($files as $key => $file) { //過濾無效的上傳 if(!empty($file["name"])) { //登記上傳文件的擴(kuò)展信息 if(!isset($file["key"])) $file["key"] = $key; $file["extension"] = $this->getExt($file["name"]); $file["savepath"] = $savePath; $file["savename"] = $this->getSaveName($file); // 自動檢查附件 if($this->autoCheck) { if(!$this->check($file)) return false; } //保存上傳文件 if(!$this->save($file)) return false; if(function_exists($this->hashType)) { $fun = $this->hashType; $file["hash"] = $fun($this->autoCharset($file["savepath"].$file["savename"],"utf-8","gbk")); } //上傳成功后保存文件信息,供其他地方調(diào)用 unset($file["tmp_name"],$file["error"]); $fileInfo[] = $file; $isUpload = true; } } if($isUpload) { $this->uploadFileInfo = $fileInfo; return true; }else { $this->error = "沒有選擇上傳文件"; return false; } } /** * 上傳單個上傳字段中的文件 支持多附件 * @access public * @param array $file 上傳文件信息 * @param string $savePath 上傳文件保存路徑 * @return string */ public function uploadOne($file,$savePath=""){ //如果不指定保存文件名,則由系統(tǒng)默認(rèn) if(empty($savePath)) $savePath = $this->savePath; // 檢查上傳目錄 if(!is_dir($savePath)) { // 嘗試創(chuàng)建目錄 if(!mkdir($savePath,0777,true)){ $this->error = "上傳目錄".$savePath."不存在"; return false; } }else { if(!is_writeable($savePath)) { $this->error = "上傳目錄".$savePath."不可寫"; return false; } } //過濾無效的上傳 if(!empty($file["name"])) { $fileArray = []; if(is_array($file["name"])) { $keys = array_keys($file); $count = count($file["name"]); for ($i=0; $i<$count; $i++) { foreach ($keys as $key) $fileArray[$i][$key] = $file[$key][$i]; } }else{ $fileArray[] = $file; } $info = []; foreach ($fileArray as $key=>$file){ //登記上傳文件的擴(kuò)展信息 $file["extension"] = $this->getExt($file["name"]); $file["savepath"] = $savePath; $file["savename"] = $this->getSaveName($file); // 自動檢查附件 if($this->autoCheck) { if(!$this->check($file)) return false; } //保存上傳文件 if(!$this->save($file)) return false; if(function_exists($this->hashType)) { $fun = $this->hashType; $file["hash"] = $fun($this->autoCharset($file["savepath"].$file["savename"],"utf-8","gbk")); } unset($file["tmp_name"],$file["error"]); $info[] = $file; } // 返回上傳的文件信息 return $info; }else { $this->error = "沒有選擇上傳文件"; return false; } } /** * 轉(zhuǎn)換上傳文件數(shù)組變量為正確的方式 * @access private * @param array $files 上傳的文件變量 * @return array */ private function dealFiles($files) { $fileArray = []; $n = 0; foreach ($files as $key=>$file){ if(is_array($file["name"])) { $keys = array_keys($file); $count = count($file["name"]); for ($i=0; $i<$count; $i++) { $fileArray[$n]["key"] = $key; foreach ($keys as $_key){ $fileArray[$n][$_key] = $file[$_key][$i]; } $n++; } }else{ $fileArray[$key] = $file; } } return $fileArray; } /** * 獲取錯誤代碼信息 * @access public * @param string $errorNo 錯誤號碼 * @return void */ protected function error($errorNo) { switch($errorNo) { case 1: $this->error = "上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值"; break; case 2: $this->error = "上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值"; break; case 3: $this->error = "文件只有部分被上傳"; break; case 4: $this->error = "沒有文件被上傳"; break; case 6: $this->error = "找不到臨時文件夾"; break; case 7: $this->error = "文件寫入失敗"; break; default: $this->error = "未知上傳錯誤!"; } return ; } /** * 根據(jù)上傳文件命名規(guī)則取得保存文件名 * @access private * @param string $filename 數(shù)據(jù) * @return string */ private function getSaveName($filename) { $rule = $this->saveRule; if(empty($rule)) {//沒有定義命名規(guī)則,則保持文件名不變 $saveName = $filename["name"]; }else { if(function_exists($rule)) { //使用函數(shù)生成一個唯一文件標(biāo)識號 $saveName = $rule().".".$filename["extension"]; }else { //使用給定的文件名作為標(biāo)識號 $saveName = $rule.".".$filename["extension"]; } } if($this->autoSub) { // 使用子目錄保存文件 $filename["savename"] = $saveName; $saveName = $this->getSubName($filename).$saveName; } return $saveName; } /** * 獲取子目錄的名稱 * @access private * @param array $file 上傳的文件信息 * @return string */ private function getSubName($file) { switch($this->subType) { case "custom": $dir = $this->subDir; break; case "date": $dir = date($this->dateFormat,time())."/"; break; case "hash": default: $name = md5($file["savename"]); $dir = ""; for($i=0;$i<$this->hashLevel;$i++) { $dir .= $name{$i}."/"; } break; } if(!is_dir($file["savepath"].$dir)) { mkdir($file["savepath"].$dir,0777,true); } return $dir; } /** * 檢查上傳的文件 * @access private * @param array $file 文件信息 * @return boolean */ private function check($file) { if($file["error"]!== 0) { //文件上傳失敗 //捕獲錯誤代碼 $this->error($file["error"]); return false; } //文件上傳成功,進(jìn)行自定義規(guī)則檢查 //檢查文件大小 if(!$this->checkSize($file["size"])) { $this->error = "上傳文件大小不符!"; return false; } //檢查文件Mime類型 if(!$this->checkType($file["type"])) { $this->error = "上傳文件MIME類型不允許!"; return false; } //檢查文件類型 if(!$this->checkExt($file["extension"])) { $this->error ="上傳文件類型不允許"; return false; } //檢查是否合法上傳 if(!$this->checkUpload($file["tmp_name"])) { $this->error = "非法上傳文件!"; return false; } return true; } // 自動轉(zhuǎn)換字符集 支持?jǐn)?shù)組轉(zhuǎn)換 private function autoCharset($fContents, $from="gbk", $to="utf-8") { $from = strtoupper($from) == "UTF8" ? "utf-8" : $from; $to = strtoupper($to) == "UTF8" ? "utf-8" : $to; if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) { //如果編碼相同或者非字符串標(biāo)量則不轉(zhuǎn)換 return $fContents; } if (function_exists("mb_convert_encoding")) { return mb_convert_encoding($fContents, $to, $from); } elseif (function_exists("iconv")) { return iconv($from, $to, $fContents); } else { return $fContents; } } /** * 檢查上傳的文件類型是否合法 * @access private * @param string $type 數(shù)據(jù) * @return boolean */ private function checkType($type) { if(!empty($this->allowTypes)) return in_array(strtolower($type),$this->allowTypes); return true; } /** * 檢查上傳的文件后綴是否合法 * @access private * @param string $ext 后綴名 * @return boolean */ private function checkExt($ext) { if(!empty($this->allowExts)) return in_array(strtolower($ext),$this->allowExts,true); return true; } /** * 檢查文件大小是否合法 * @access private * @param integer $size 數(shù)據(jù) * @return boolean */ private function checkSize($size) { return !($size > $this->maxSize) || (-1 == $this->maxSize); } /** * 檢查文件是否非法提交 * @access private * @param string $filename 文件名 * @return boolean */ private function checkUpload($filename) { return is_uploaded_file($filename); } /** * 取得上傳文件的后綴 * @access private * @param string $filename 文件名 * @return boolean */ private function getExt($filename) { $pathinfo = pathinfo($filename); return $pathinfo["extension"]; } /** * 取得上傳文件的信息 * @access public * @return array */ public function getUploadFileInfo() { return $this->uploadFileInfo; } /** * 取得最后一次錯誤信息 * @access public * @return string */ public function getErrorMsg() { return $this->error; } }4.2 測試 4.2.1 終端下執(zhí)行 composer install,這時會生成vendor目錄,及其他文件
yzm@Alert MINGW64 /i/phpstudy/WWW/uploadfile $ composer install4.2.2 新建uploadfile/test/UpploadFileTest.php、uploadfile/test/UpploadFile.html
UpploadFileTest.php
maxSize = 1*1024*1024; // 默認(rèn)為-1,不限制上傳大小 $upload->savePath = "./upload/"; // 上傳根目錄 $upload->saveRule = "uniqid"; // 上傳文件的文件名保存規(guī)則 $upload->uploadReplace = true; // 如果存在同名文件是否進(jìn)行覆蓋 $upload->autoSub = true; // 上傳子目錄開啟 $upload->subType = "date"; // 上傳子目錄命名規(guī)則 $upload->allowExts = ["jpg", "png"]; // 允許類型 if ($upload->upload()) { var_dump($upload->getUploadFileInfo()); } else { var_dump($upload->getErrorMsg()); }
UpploadFile.html
uploadfile test
4.2.3 本地瀏覽器訪問uploadfile/test/UpploadFile.html進(jìn)行測試
五、添加 README.md、LICENSE、.gitignore等文件,項目最終結(jié)構(gòu)如下:我的包GitHub地址├─uploadfile 擴(kuò)展包根目錄 │ ├─src 擴(kuò)展包代碼目錄 │ │ ├─UploadFile.php │ ├─test 測試目錄 │ │ ├─uploadfile.html │ │ ├─UpploadfileTest.php │ ├─.gitignore │ ├─composer.json │ ├─LICENSE │ └─README.md六、推送到 GitHub
git add . git commit -m "init" git tag v1.0.0 // 記住打一個版本號 git push origin master git push v1.0.0七、將 GitHub 上的包提交到 Packagist
首先要在 Packagist 上注冊賬號并登錄(可以用 GitHub 直接登錄)
點擊頂部導(dǎo)航條中的 Summit 按鈕
在輸入框中輸入 GitHub 上的剛才包地址,如:https://github.com/guanguans/uploadfile
然后點擊 Check 按鈕 Packagist 會去檢測此倉庫地址的代碼是否符合 Composer 的 Package 包的要求
檢測正常的話,會出現(xiàn) Submit 按鈕,再點擊一下 Submit 按鈕,我們的包就提交到 Packagist 上了
八、設(shè)置 composer 包自動更新上面提交上的包提交的包,當(dāng)我們更新 GitHub 倉庫時,Packagist 上面的的包并不會自動更新,現(xiàn)在我們來設(shè)置一下自動更新
8.1 復(fù)制 Profile API Token 8.2 打開 GitHub 項目 setting,選擇 Integrations & services,添加 packagist service,點擊 Test service 8.3 驗證是否已經(jīng)自動更新移步 Packagist 包主頁,發(fā)現(xiàn)已經(jīng)沒有了紅色的圈住的提示,說明設(shè)置自動更新成功。
九、項目中使用我以 Laravel 中使用舉例
composer create-project laravel/laravel cd laravel composer require guanguans/uploadfile其他
本文通用上傳類由 ThinkPHP 中 UploadFile.class.php 修改
本文首發(fā)琯琯博客,可前往瀏覽更多文章。
本文為琯琯原創(chuàng)文章,轉(zhuǎn)載無需和我聯(lián)系,但請注明來自琯琯博客 https://guanguans.cn
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/28448.html
摘要:想要更好的利用協(xié)同工作,學(xué)會創(chuàng)建自己的包是一項必不可少的技能。編輯項目的或,增加一項配置,例如以上配置使用中國全量鏡像網(wǎng)站作為默認(rèn)中央倉庫。創(chuàng)建自己的包創(chuàng)建一個包只需兩步填寫包描述信息寫代碼。通過簡單兩步,我們創(chuàng)建的自己的包。 轉(zhuǎn)載請注明文章出處:https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請求 cookie web響應(yīng) ...
摘要:開源的論壇網(wǎng)站開源的論壇源代碼接口管理接口環(huán)境下環(huán)境一鍵安裝軟件二前端資源中國淘寶鏡像在國內(nèi),由于墻的原因,安裝包速度很慢,所以,這里建議使用淘寶提供的鏡像安裝前端資源。 為者常成,行者常至。 一、PHP資料 1、V2EX way to explore 分享和探索的地方2、Laravel China 中國最大的 Laravel 和 PHP 開發(fā)者社區(qū)3、Composer使用方法4、Pa...
摘要:開源的論壇網(wǎng)站開源的論壇源代碼接口管理接口環(huán)境下環(huán)境一鍵安裝軟件二前端資源中國淘寶鏡像在國內(nèi),由于墻的原因,安裝包速度很慢,所以,這里建議使用淘寶提供的鏡像安裝前端資源。 為者常成,行者常至。 一、PHP資料 1、V2EX way to explore 分享和探索的地方2、Laravel China 中國最大的 Laravel 和 PHP 開發(fā)者社區(qū)3、Composer使用方法4、Pa...
摘要:運行來安裝指定的擴(kuò)展。這更便于用戶辨別是否是的擴(kuò)展。當(dāng)用戶運行安裝一個擴(kuò)展時,文件會被自動更新使之包含新擴(kuò)展的信息。上述代碼表明該擴(kuò)展依賴于包。例如,上述的條目聲明將對應(yīng)于別名。為達(dá)到這個目的,你應(yīng)當(dāng)在公開發(fā)布前做測試。 簡述 擴(kuò)展是專門設(shè)計的在 Yii 應(yīng)用中隨時可拿來使用的, 并可重發(fā)布的軟件包。 基礎(chǔ) 例如, yiisoft/yii2-debug 擴(kuò)展在你的應(yīng)用的每個頁面底部添加...
閱讀 4933·2021-11-25 09:43
閱讀 1186·2021-11-24 09:38
閱讀 1892·2021-09-30 09:54
閱讀 2800·2021-09-23 11:21
閱讀 2367·2021-09-10 10:51
閱讀 2368·2021-09-03 10:45
閱讀 1163·2019-08-30 15:52
閱讀 1766·2019-08-30 14:13