废话不多说,直接上代码
首先修改config文件下的filesystem.php文件
<?php return [ // 默认磁盘 'default' => env('filesystem.driver', 'local'), // 磁盘列表 'disks' => [ 'local' => [ 'type' => 'local', 'root' => app()->getRuntimePath() . 'storage', ], 'public' => [ // 磁盘类型 'type' => 'local', // 磁盘路径 'root' => './upload',//app()->getRootPath() . 'public/upload', //这里修改成我这样即可,当然你可以自己定义你的路径 // 磁盘路径对应的外部URL路径 'url' => '/upload', // 可见性 'visibility' => '',//public ], // 更多的磁盘配置信息 ], //以下完全是自定义,定义你的上传文件路径,自定义即可 'filetype' => [ 0 => 'other', //其他(未知)文件或图片 1 => 'images', //图片 2 => 'images/logo', //网站logo 3 => 'images/favicon', //网站favicon 4 => 'images/avatar', //用户头像 5 => 'images/article', //文章配图 6 => 'images/source', //资源配图 7 => 'images/carousel', //轮播配图 8 => 'images/product', //产品图片 9 => 'images/notice', //通知图片 10 => 'images/sys', //系统产生的图片 11 => 'images/chat', //聊天图片 12 => 'images/liveroom', //直播间头像 13 => 'images/book', //书籍封面 30 => 'file', //文件 34 => 'file/article', //文章里面的文件 35 => 'file/source', //资源文件 37 => 'file/product', //产品文件 38 => 'file/notice', //通知里面文件 39 => 'file/sys', //系统产生的文件 40 => 'file/chat', //聊天文件 ] ];
- upload.php
首先命名空间还是要定义的,我这里写在公共文件夹common里面了,app>commen>model 下
<?php
namespace app\common\model;
这里引用到Filesystem类,和think下的file的类(如果需要对图片作一些处理,需要自己改进引用到image类,需要自己安装tp下的image包)
use think\facade\Filesystem;
use think\File;
use think\Image; //自选
开始创建Upload类吧
class Upload{
//初始化一些参数
protected $field ='file'; //请求字段
protected $maxsize ='5*1024*1024';//最大上传大小5M
protected $ext ='';//限制上传后缀
protected $rule ='';//命名规则,md5/date/sha1 3种存储方式,默认以date方式
protected $rename =true;//是否重命名,默认true
protected $type =0;//默认上传目录
protected $url ='';//'/upload';
protected $path ='';//'./upload';
protected $typepath='';//上传创建的路径
protected $ischeck =false;//默认需要校验
protected $config =[];
protected $validate='';
总得对初始化的参数做一些处理吧
/**
* Upload constructor.
* @param $options
*/
function __construct($options){
$this->config=[
'field' => !empty($options['field'])?$options['field']:$this->field,
'maxsize' => !empty($options['maxsize'])?$options['maxsize']:$this->maxsize,
'ext' => !empty($options['ext'])?$options['ext']:$this->ext,
'rule' => !empty($options['rule'])?($options['rule']=='date'?'':$options['rule']):$this->rule,
'rename' => $options['rename']==false?$options['rename']:$this->rename,
'type' => $options['type']!=(null || '')?$options['type']:$this->type,
'ischeck' => !empty($options['ischeck'])?$options['ischeck']:$this->ischeck,
];//集中配置app()->config->get('filesystem.disks.public.url')
$this->validate='filesize:'.$this->config['maxsize'].'|fileExt:'.$this->config['ext'];//集中验证规则
$this->path=app()->config->get('filesystem.disks.public.root').'/'.$this->actdir($this->config['type']);
$this->typepath=$this->actdir($this->config['type']);
$this->url=app()->config->get('filesystem.disks.public.url').'/'.$this->actdir($this->config['type']);
}
根据类型去创建对应的文件目录吧
/**
* @上传文件获取上传目录
* @param int $type 0=公共文件目录,1=商品分类图标,2=商品图片,3=文章分类图标,4=文章封面图、插图,
* 5=活动图片,6=会员头像存储,7=系统用户头像存储,8=评论、回复图片,9=广告图片,10=公告图片,11=消息图片,
* 12=轮播图片,13=品牌图标,16=商品视频,17=活动(宣传)视频,18=文章视频,99=其他未知类型文件
* @return string
*/
private function actdir($type=0){
// 这些类型在最上面的filesystem.php里面定义后去获取即可
// $arr=[
// 0 => 'other', //其他(未知)文件或图片
// 1 => 'images', //图片
// 2 => 'images/logo', //网站logo
// 3 => 'images/favicon', //网站favicon
// 4 => 'images/avatar', //用户头像
// 5 => 'images/article', //文章配图
// 6 => 'images/source', //资源配图
// 7 => 'images/carousel', //轮播配图
// 8 => 'images/product', //产品图片
// 9 => 'images/notice', //通知图片
// 10 => 'images/sys', //系统产生的图片
// 11 => 'images/chat', //聊天图片
// 30 => 'file', //文件
// 34 => 'file/article', //文章里面的文件
// 35 => 'file/source', //资源文件
// 37 => 'file/product', //产品文件
// 38 => 'file/notice', //通知里面文件
// 39 => 'file/sys', //系统产生的文件
// 40 => 'file/chat', //聊天文件
// ];
$arr=app()->config->get('filesystem.filetype'); //获取初始定义的目录
return $arr[$type];
}
开始上传,也就是需要开始对上传的图片进行处理的地方了
/**
* @上传入口
*/
public function uploadfile(){
$files = request()->file($this->config['field']); //获取文件
//判断存储目录是否存在,不存在则生成
if(!file_exists($this->path)){
mkdir($this->path,0777,true);//生成含有下级目录
}
if(is_array($files)){
return self::handlemultfile($files);
}else{
return self::handleonlyfile($files);
}
}
handlemultfile多文件上传入口
/**
* @多文件上传
* @param $files
*/
private function handlemultfile($files){
foreach($files as $file){
return self::handleonlyfile($file);
}
}
handleonlyfile单文件上传入口
/**
* @单文件上传
* @param $file
*/
private function handleonlyfile($file){
$fileSystem=new Filesystem();
$oldname=$file->getOriginalName();//['name']; //获取原名称
if($this->config['ischeck']) { //1.验证文件
try{
validate([$this->config['field']=>$this->validate])->check($file);
}catch (\think\exception\ValidateException $e){
return self::_error($e->getMessage());
}
}
if($this->config['rename']) {//2.会按照规则重命名
$info = $fileSystem::disk('public')->putFile( $this->typepath, $file, $this->config['rule']);
}else{ //3.不会重命名,且不会覆盖
$info = $fileSystem::disk('public')->putFileAs( $this->typepath.'/'.date('Ymd'), $file, $oldname);
}
if($info){ //$info是一个文件的路径
$filepath=app()->config->get('filesystem.disks.public.root').'/'.$info;
$fileNew=new File($filepath);
$ext=$fileNew->extension();//获取文件后缀
$fileName=$fileNew->getFilename();
//处理商品图片文件
if(in_array($ext,['png','jpg','jpeg','gif','tif','pic','ico','webp','pcx','bmp']) && $this->config['type']==8){
self::thumbimg($filepath); //处理商品图片(type=8)
}
//存入数据库,返回id值
return self::saveToBase($filepath);
}else{
return self::_error('上传出错,联系管理员');
}
}
获取文件后缀
/**
* 获取文件后缀,这个作法是不科学的,请使用原生的file的获取文件后缀
**/
private function getNameAndExt($filename){
$arr=explode('.',$filename);
return $arr;
}
简单处理比如商品图片(此处只是示例,有需要的自己扩展) 这里需要引用Image包扩展
/**
* php裁剪图像
* @param $filename
*/
private function cropimg($filepath){
$fileNew=new File($filepath);
$fileNewPath=str_replace($fileNew->getFilename(),'',$filepath);
$width=300;$height=300;$pwidth=100;$pheight=30;
$image = Image::open($filepath);
$arr=self::getNameAndExt($fileNew->getFilename());
$newfilename=$arr[0].'_'.$width.'_'.$height.'.'.$arr[1];
if($image->crop($width,$height,$pwidth,$pheight)->save($fileNewPath.$newfilename)){
return true;
}
return false;
}
/**
* php生成略缩图
* @param $filename
*/
private function thumbimg($filepath){
$width=300;$height=300;
$image= Image::open($filepath);
$fileNew=new File($filepath);
$arr=self::getNameAndExt($fileNew->getFilename());
$newfilename1=$arr[0].'_'.$width.'_'.$height.'.'.$arr[1];
$newfilename2=$arr[0].'_'.($width/6).'_'.($height/6).'.'.$arr[1];
$newfilename3=$arr[0].'_'.($width/3).'_'.($height/3).'.'.$arr[1];
$newfilename4=$arr[0].'_'.($width/2).'_'.($height/2).'.'.$arr[1];
$image->thumb($width,$height)->save($this->path.'/'.date('Ymd').'/'.$newfilename1);
$image->thumb($width/6,$height/6)->save($this->path.'/'.date('Ymd').'/'.$newfilename2);
$image->thumb($width/3,$height/3)->save($this->path.'/'.date('Ymd').'/'.$newfilename3);
$image->thumb($width/2,$height/2)->save($this->path.'/'.date('Ymd').'/'.$newfilename4);
}
res方法是一个公共方法,在common.php里面自行创建
function res($code=0,$msg='',$data=null,$count=0){
return json([
'code' => $code,
'msg' => $msg,
'data' => $data,
'count' => $count
]);
}
成功返回
失败返回
/**
* @成功返回
* @param $data
* @return \think\response\Json
*/
private function _success($data){
return res(0,'上传成功',$data,1);
}
/**
* @失败返回
* @param $msg
* @return \think\response\Json
*/
private function _error($msg){
return res(1,$msg);
}
存入数据库或OSS之类的在此处扩展,需要自己引入数据库model
CREATE TABLE `XX_files` (
`id` char(32) NOT NULL COMMENT '图片ID',
`filename` varchar(50) DEFAULT '' COMMENT '图片名称',
`ext` varchar(20) DEFAULT '' COMMENT '扩展名',
`size` int(10) DEFAULT '0' COMMENT '文件大小',
`url` varchar(255) DEFAULT '' COMMENT '绝对请求地址',
`path` varchar(255) DEFAULT '' COMMENT '物理地址',
`type` tinyint(3) DEFAULT '0' COMMENT '图片分类',
`cattype` varchar(20) DEFAULT 'Local' COMMENT '存储引擎,本地,xx云等',
`addtime` datetime DEFAULT NULL COMMENT '创建时间',
`isdel` smallint(12) unsigned DEFAULT '0' COMMENT '删除标志0=默认1=删除',
`jsondata` text COMMENT '存入的JSON字符串',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `id` (`id`) USING BTREE,
KEY `isdel` (`isdel`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='全部文件表';
private function saveToBase($filepath){
//如果需要存入OSS,这里需要自己扩展自己的代码
//扩展代码
//扩展代码,然后再进行存储存入后的路径
$saveName=self::dir_replace($filepath);
$fileNew=new File($filepath);
$db=new Files(); //我这里叫files表,作演示
$data=[
'id' => md5($fileNew->getFilename()),
'filename' => $fileNew->getFilename(),
'ext' => $fileNew->extension(),
'size' => filesize($filepath),
'url' => ltrim($saveName,'.'), //去掉左边第一个.
'path' => $saveName,
'type' => $this->config['type'],
'cattype' => 'Local',//Local是存入本地的意思
'addtime' => toDate(),
];
$data['jsondata']=json_encode($data,JSON_UNESCAPED_SLASHES);
if($db->addData($data)){
return $this->_success(json_encode($data,JSON_UNESCAPED_SLASHES));
}else{
return $this->_success(json_encode([
'id' => $data['filename'],
'filename' => $data['filename'],
'ext' => $data['ext'],
'size' => $data['size'],
'url' => $data['url'],
'type' => $this->config['type'],
'path' => $data['path'],
],JSON_UNESCAPED_SLASHES));
}
}
辅助方法 - 转换路径,便于在win和linux都能用
/**
* 替换相应的字符
* @param string $path 路径
* @return string
*/
public function dir_replace($path){
return str_replace('//','/',str_replace('\\','/',$path));
}
base64位图片上传
/**
* 上传blob流文件
* @param $imgfile
* @param int $typeid
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
*/
public function upload_avatar($imgfile,$mode=1){
//接收
$img=$imgfile;
//文件夹日期
$ymd = date("Ymd",time());
//图片路径地址
$fullpath = $this->path.'/'.$ymd;
if(!is_dir($fullpath)){
mkdir($fullpath,0777,true);
}
$types = empty($types)? array('jpg', 'gif', 'png', 'jpeg', 'ico'):$types;
$img = str_replace(array('_','-'), array('/','+'), $img);
$b64img = substr($img, 0,100);
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $b64img, $matches)) {
$ext = $matches[2];
if (!in_array($ext, $types)) {
return res(1,'文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。');
}
$img = str_replace($matches[1], '', $img);
$img = base64_decode($img);
$photo = '/' . md5(date('YmdHis') . rand(1000, 9999)) . '.' . $ext;
file_put_contents($fullpath . $photo, $img);//写入图片
//存入到数据库
//$fileurl=$this->url.'/'.$ymd.$photo;//图片路径+文件ming
$filepath = $this->path.'/'.$ymd.$photo;
if($mode==1){
return self::saveToBase($filepath);//存入数据库
}
//其他操作等
// $data=[
// 'id' => md5($photo),
// 'filename' => $photo,
// 'ext' => $ext,
// 'size' => filesize($this->path.'/'.$ymd.$photo),
// 'url' => $this->url.'/'.$ymd.$photo,
// 'path' => $this->path.'/'.$ymd.$photo,
// 'type' => $this->config['type'],
// 'cattype' => 'Local',//
// 'addtime' => toDate(),
// ];
// $data['jsondata']=json_encode($data,JSON_UNESCAPED_SLASHES);
// $db=new Files();
// if($db->addData($data)){
// return $this->_success(json_encode($data,JSON_UNESCAPED_SLASHES));
// }else{
// return $this->_error('头像保存失败');
// }
}else{
return $this->_error('您上传的头像已丢失,请重新上传!');
}
}
完整代码
自此,整个上传类就结束,如果有小伙伴发现问题,请及时反馈给我,大家相互学习。有任何疑问,评论区见。
kk
写的很详细,辛苦了
很好,学习了
看看tp的
看一看
看看
欢迎