Разработайте универсальный пакет для загрузки файлов composer, опубликуйте его в Packagist и протестируйте в Laravel.
Сначала GitHub создает новое хранилище с именем Файл загрузки и клонирует его локально.
$ git clone [email protected]github.com:guanguans/uploadfile.git $ cd uploadfile
2. Инициализируйте проект и сгенерируйте файл composer.json
2.1 шаги
[email protected] 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 (/ ) [yzm/try-make-package]: guanguans/uploadfile Description []: A generic file upload package Author [guanguans <[email protected]>, n to skip]: guanguans <[email protected]> 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: "A generic file upload package" "type": "library", "require": { "php": ">=5.4" }, "require-dev": { "php": ">=5.4" }, "license": "MIT", "authors": [ { "name": "guanguans", "email": "[email protected]" } ], "minimum-stability": "dev" } Do you confirm generation [yes]? yes
2.2 Объяснение шага
[email protected] 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. Enter the project namespace // Note that/ must conform to [a-z0-9_. -]+/[a-z0-9_. -]+ Package name ( / ) [dell/htdocs]: yourname/projectname // 2. Project description Description []: This is a test // 3. Enter the author's information, you can return directly. Author [guanguans <[email protected]>, n to skip]: // 4. Enter the lowest stable version, stable, RC, beta, alpha, dev Minimum Stability []: dev // 5. Enter the project type. Package Type (e.g. library, project, metapackage, composer-plugin) []: library // 6. Enter the type of authorization License []: > Define your dependencies. // 7. Input dependency information Would you like to define your dependencies (require) interactively [yes]? // If dependencies are required, enter the dependencies to be installed Search for a package: php // Enter version number Enter the version constraint to require (or leave blank to use the latest version): >=5.4.0 // If more than one is needed, repeat the above two steps // 8. Is it necessary to require-dev? Would you like to define your dev dependencies (require-dev) interactively [yes]? // Operations Ibid. { "name": "guanguans/uploadfile", Description: "A generic file upload package" "type": "library", "require": { "php": ">=5.4" }, "require-dev": { "php": ">=5.4" }, "license": "MIT", "authors": [ { "name": "guanguans", "email": "[email protected]" } ], "minimum-stability": "dev" } // 9. Whether to generate composer. JSON Do you confirm generation [yes]? yes
3. Добавление Автоматической Загрузки
Сгенерировано на предыдущем шаге composer.json Вторичное добавление
"autoload": {
"psr-4": {
"Guanguans\\": "src/"
}
}IV. Строительные Проекты
4.1 NEWuploadfile/src/UploadFile.php
├─uploadfile │ ├─src │ │ ├─UploadFile.php │ └─composer.json
[email protected]>
*/
Namespace Guanguans; // Note that namespaces are consistent with composer. JSON
class UploadFile
{
private $config = [
'maxSize'=>-1, //maximum upload file
'Support Multi'=> true, /// Supporting multi-file upload
'allowExts'=> [], // File suffixes allowed to upload are left blank without suffix checking
'allowTypes'=> [], // File type allowed to upload is left blank and unchecked
'thumb'=> false, // thumbnail the uploaded image
'imageClassPath'=>'ORG.Util.Image', //gallery class package path
'thumbMaxWidth'=>', //thumbnail maximum width
'thumbMaxHeight'=>', //thumbnail maximum height
'thumbPrefix'=>'thumb_', //thumbnail prefix
'thumbSuffix' => '',
'thumbPath'=>', //thumbnail save path
'thumbFile'=>', //thumbnail file name
'thumbExt'=>', //thumbnail extension
'thumbRemove Origin'=> false, // Remove the original image
'thumbType'=> 1, // thumbnail generation mode 1, intercept 0 according to the size of the settings, and abbreviate in equal proportion to the original image
'zipImages'=> false, //compressed picture file upload
'autoSub'=> false, // Enable subdirectories to save files
'SubType'=>'hash', //subdirectory creation can use hash date custom
SubDir'=>', //subdirectory name subType is valid after custom mode
'dateFormat' => 'Ymd',
'hashLevel'=> 1, // hash directory hierarchy
'savePath'=>', // Upload File Save Path
'autoCheck'=> true, /// whether to automatically check attachments
'uploadReplace'=> false, // whether the same name is overwritten
'saveRule'=>'uniqid', //Upload File Naming Rules
'hashType'=>'md5_file', //Upload file Hash rule function name
];
// Error message
private $error = '';
// Upload Successful File Information
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]);
}
/**
* Architectural functions
* @access public
*@ Param array $config upload parameter
*/
public function __construct($config=[]) {
if(is_array($config)) {
$this->config = array_merge($this->config,$config);
}
}
/**
* Upload a file
* @access public
*@ Param mixed $name data
*@ Param string $value data table name
* @return string
*/
private function save($file) {
$filename = $file['savepath'].$file['savename'];
if(!$this->uploadReplace && is_file($filename)) {
// Documents with the same name are not overwritten
This - > error = file already exists! '.$filename;
return false;
}
// If it is an image file, check the file format
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 = illegal image file;
return false;
}
}
if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) {
This - > error = file upload save error! ';
return false;
}
if($this->thumb && in_array(strtolower($file['extension']), ['gif','jpg','jpeg','bmp','png'])) {
$image = getimagesize($filename);
if(false !== $image) {
// Generate thumbnails for image files
$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']; // custom thumbnail extension
// Generating image thumbnails
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) {
// Delete the original image after generating thumbnails
unlink($filename);
}
}
}
if($this->zipImags) {
// TODO on-line decompression of picture compression packages
}
return true;
}
/**
* Upload all files
* @access public
*@ Param string $savePath upload file save path
* @return string
*/
public function upload($savePath ='') {
// If the save file name is not specified, the system defaults
if(empty($savePath))
$savePath = $this->savePath;
// Check the upload directory
if(!is_dir($savePath)) {
// Check if the directory is coded
if(is_dir(base64_decode($savePath))) {
$savePath = base64_decode($savePath);
}else{
// Try to create a directory
if(!mkdir($savePath)){
$this - > error = upload directory'. $savePath.'None exists';
return false;
}
}
}else {
if(!is_writeable($savePath)) {
$this - > error = upload directory'. $savePath.'Unwritable';
return false;
}
}
$fileInfo = [];
$isUpload = false;
// Get Uploaded File Information
// Information Processing for $_FILES Array
$files = $this->dealFiles($_FILES);
foreach($files as $key => $file) {
// Filling Invalid Uploads
if(!empty($file['name'])) {
// Extended information for registering uploaded files
if(!isset($file['key'])) $file['key'] = $key;
$file['extension'] = $this->getExt($file['name']);
$file['savepath'] = $savePath;
$file['savename'] = $this->getSaveName($file);
// Automatic inspection of accessories
if($this->autoCheck) {
if(!$this->check($file))
return false;
}
// Save uploaded files
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'));
}
// After successful upload, save file information for call elsewhere
unset($file['tmp_name'],$file['error']);
$fileInfo[] = $file;
$isUpload = true;
}
}
if($isUpload) {
$this->uploadFileInfo = $fileInfo;
return true;
}else {
$this - > error ='No upload file selected';
return false;
}
}
/**
* Supporting multiple attachments by uploading files in a single upload field
* @access public
*@ Param array $file uploads file information
*@ Param string $savePath upload file save path
* @return string
*/
public function uploadOne($file,$savePath=''){
// If the save file name is not specified, the system defaults
if(empty($savePath))
$savePath = $this->savePath;
// Check the upload directory
if(!is_dir($savePath)) {
// Try to create a directory
if(!mkdir($savePath,0777,true)){
$this - > error = upload directory'. $savePath.'None exists';
return false;
}
}else {
if(!is_writeable($savePath)) {
$this - > error = upload directory'. $savePath.'Unwritable';
return false;
}
}
// Filling Invalid Uploads
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){
// Extended information for registering uploaded files
$file['extension'] = $this->getExt($file['name']);
$file['savepath'] = $savePath;
$file['savename'] = $this->getSaveName($file);
// Automatic inspection of accessories
if($this->autoCheck) {
if(!$this->check($file))
return false;
}
// Save uploaded files
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 uploaded file information
return $info;
}else {
$this - > error ='No upload file selected';
return false;
}
}
/**
* Converting Upload File Array Variables to the Right Way
* @access private
*@ File variables uploaded by 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;
}
/**
* Get error code information
* @access public
*@ Param string $errorNo error number
* @return void
*/
protected function error($errorNo) {
switch($errorNo) {
case 1:
$this - > error = the uploaded file exceeds the limit of the upload_max_filesize option in php.ini';
break;
case 2:
The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form.
break;
case 3:
This - > error ='Only part of the file is uploaded';
break;
case 4:
$this - > error = no file uploaded';
break;
case 6:
$this - > error ='temporary folder not found';
break;
case 7:
$this - > error = file write failure;
break;
default:
This - > error = Unknown upload error! ';
}
return ;
}
/**
* Get the saved file name according to the upload file naming rules
* @access private
*@ Param string $filename data
* @return string
*/
private function getSaveName($filename) {
$rule = $this->saveRule;
If (empty ($rule) {// no naming rules are defined, the file name remains unchanged
$saveName = $filename['name'];
}else {
if(function_exists($rule)) {
// Generate a unique file identifier using functions
$saveName = $rule().".".$filename['extension'];
}else {
// Use the given file name as the identification number
$saveName = $rule.".".$filename['extension'];
}
}
if($this->autoSub) {
// Use subdirectories to save files
$filename['savename'] = $saveName;
$saveName = $this->getSubName($filename).$saveName;
}
return $saveName;
}
/**
* Get the name of the subdirectory
* @access private
*@ File information uploaded by 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;
}
/**
* Check uploaded files
* @access private
*@ Param array $file file file information
* @return boolean
*/
private function check($file) {
if($file['error']!== 0) {
// File upload failed
// Capture error code
$this->error($file['error']);
return false;
}
// File upload was successful and custom rule checking was performed
// Check file size
if(!$this->checkSize($file['size'])) {
$this - > error = upload file size does not match! ';
return false;
}
// Check file Mime type
if(!$this->checkType($file['type'])) {
This - > error = upload file MIME type is not allowed! ';
return false;
}
// Check file type
if(!$this->checkExt($file['extension'])) {
$this - > error ='upload file type is not allowed';
return false;
}
// Check for legal upload
if(!$this->checkUpload($file['tmp_name'])) {
$this - > error = illegal upload of files! ';
return false;
}
return true;
}
// Automatic Conversion Character Set Support Array Conversion
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))) {
// If the encoding is the same or if the non-string scalar is not converted
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;
}
}
/**
* Check uploaded files类型是否合法
* @access private
*@ Param string $type data
* @return boolean
*/
private function checkType($type) {
if(!empty($this->allowTypes))
return in_array(strtolower($type),$this->allowTypes);
return true;
}
/**
* Check uploaded files后缀是否合法
* @access private
*@ Param string $ext suffix name
* @return boolean
*/
private function checkExt($ext) {
if(!empty($this->allowExts))
return in_array(strtolower($ext),$this->allowExts,true);
return true;
}
/**
* Check file size for legitimacy
* @access private
*@ Param integer $size data
* @return boolean
*/
private function checkSize($size) {
return !($size > $this->maxSize) || (-1 == $this->maxSize);
}
/**
* Check for illegal submission of documents
* @access private
*@ Param string $filename file name
* @return boolean
*/
private function checkUpload($filename) {
return is_uploaded_file($filename);
}
/**
* Get the suffix of the uploaded file
* @access private
*@ Param string $filename file name
* @return boolean
*/
private function getExt($filename) {
$pathinfo = pathinfo($filename);
return $pathinfo['extension'];
}
/**
* Get information about uploaded files
* @access public
* @return array
*/
public function getUploadFileInfo() {
return $this->uploadFileInfo;
}
/**
* Get the last error message
* @access public
* @return string
*/
public function getErrorMsg() {
return $this->error;
}
}4.2 испытание
4.2.1 Установка композитора выполнения терминала Это создает каталоги поставщиков и другие документы
[email protected] MINGW64 /i/phpstudy/WWW/uploadfile $ composer install
4.2.2 NEWuploadfile/test/UpploadFileTest.php、uploadfile/test/UpploadFile.html
- 4.2.2 NEWuploadfile/test/UpploadFileTest.php、uploadfile/test/UpploadFile.html
maxSize = 1 * 1024 * 1024; // Default is - 1, no limit on upload size
$upload - > savePath ='. / upload /'; // upload the root directory
$upload - > saveRule ='uniqid'; // File name saving rules for uploaded files
$upload - > uploadReplace = true; // If a file with the same name exists, whether it is overwritten or not
$upload - > autoSub = true; // upload subdirectory open
$upload - > subType ='date'; // Upload subdirectory naming rules
$upload - > allowExts = ['jpg','png']; // allowed type
if ($upload->upload()) {
var_dump($upload->getUploadFileInfo());
} else {
var_dump($upload->getErrorMsg());
}- 4.2.2 NEWuploadfile/test/UpploadFileTest.php、uploadfile/test/UpploadFile.html
uploadfile test
4.2.3 Доступ к Локальному браузеру uploadfile/test/UpploadFile.html Тестирование
Пять, добавьте README.md、ЛИЦЕНЗИЯ、.gitignore Окончательная структура проекта выглядит следующим образом: Адрес моего пакета на GitHub
-uploadfile Extended Package Root Directory -src Extension Package Code Directory │ │ ├─UploadFile.php -test test test catalogue │ │ ├─uploadfile.html │ │ ├─UpploadfileTest.php │ ├─.gitignore │ ├─composer.json │ ├─LICENSE │ └─README.md
6. Переход на GitHub
git add . git commit -m 'init' Git tag v1.0.0//Remember to type a version number git push origin master git push v1.0.0
7. Отправляйте пакеты на GitHub упаковщику
- Во-первых, зарегистрируйте свою учетную запись на Packagist и войдите в систему (вы можете войти непосредственно на GitHub).
- Нажмите кнопку Отправить в верхней панели навигации
- В поле ввода введите адрес предыдущего пакета на GitHub, например:
https://github.com/guanguans/uploadfile - Затем нажмите на кнопку Проверить упаковщика, чтобы проверить, соответствует ли код адреса склада требованиям пакета Composer.
Если обнаружение в норме, появится кнопка Отправить, затем нажмите кнопку Отправить, и наш пакет будет отправлен упаковщику.
8. Настройка пакета composer для автоматического обновления
Когда мы обновляем репозиторий GitHub, пакет в Packagist автоматически не обновляется. Теперь давайте настроим автоматическое обновление.
8.1 Копирование маркера API профиля
8.2 Откройте настройки проекта на GitHub, выберите “Интеграция и службы”, Добавьте службу упаковщика, нажмите “Служба тестирования”.
8.3 Убедитесь, что были сделаны автоматические обновления
Просмотрите домашнюю страницу пакета Packagist и обнаружите, что там нет красной подсказки о блокировке, указывающей на то, что настройки автоматически успешно обновлены.
IX. Использование в проектах
Я использую Laravel в качестве примера
composer create-project laravel/laravel cd laravel composer require guanguans/uploadfile
Другой
- Этот общий класс загрузки изменяется с помощью файла загрузки. класс. PHP в ThinkPHP
- Первая статья Блог Читайте больше статей.
Эта статья В китайском стиле Оригинальные статьи, перепечатанные без контакта со мной, но, пожалуйста, укажите из Блог Гуань гуань https://guanguanguans.cn