238 lines
6.3 KiB
PHP
238 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace app\common\model;
|
|
|
|
use app\common\model\driver\AliyunOss;
|
|
use app\common\model\driver\Local;
|
|
use app\common\model\driver\TxyunOss;
|
|
use think\Exception;
|
|
|
|
class FileUpload
|
|
{
|
|
|
|
/**
|
|
* @var int 储存策略
|
|
*/
|
|
protected $policy;
|
|
|
|
/**
|
|
* @var int 上传用户
|
|
*/
|
|
protected $uid;
|
|
|
|
/**
|
|
* @var array 上传数据
|
|
*/
|
|
protected $info;
|
|
|
|
/**
|
|
* @var int 最大上传大小
|
|
*/
|
|
protected $max_size;
|
|
|
|
|
|
/**
|
|
* 设置来源信息
|
|
* @param $uid
|
|
* @param $policy
|
|
* @param $max_size
|
|
* @return FileUpload
|
|
*/
|
|
public function source($uid,$policy,$max_size): FileUpload
|
|
{
|
|
$this->uid = $uid;
|
|
$this->policy = $policy;
|
|
$this->max_size = $max_size;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* 检查文件信息
|
|
* @throws Exception
|
|
*/
|
|
protected function check(){
|
|
|
|
if(empty($this->info['file']['folder'])){
|
|
throw new Exception('上传目标文件夹不存在');
|
|
}
|
|
|
|
if(empty($this->info['file']['data'])){
|
|
throw new Exception('请选择上传的文件');
|
|
}
|
|
|
|
if(empty($this->info['file']['size'])){
|
|
throw new Exception('文件大小异常');
|
|
}
|
|
|
|
if(empty($this->info['file']['name'])){
|
|
throw new Exception('上传文件名异常');
|
|
}
|
|
|
|
if($this->policy['type'] == 'remote'){
|
|
throw new Exception('您不可以使用该存储策略');
|
|
}
|
|
|
|
if(!empty($this->max_size)){
|
|
if($this->info['file']['size'] > $this->max_size){
|
|
throw new Exception('单文件最大上传大小'.countSize($this->max_size));
|
|
}
|
|
}
|
|
|
|
if(!empty($this->policy['filetype'])){
|
|
$file_ext = $this->getFileExt($this->info['file']['name']);
|
|
$allow_ext = explode(',',$this->policy['filetype']);
|
|
if(!in_array($file_ext,$allow_ext)){
|
|
throw new Exception('不允许上传'.$file_ext.'类型的文件');
|
|
}
|
|
}
|
|
|
|
if(empty($this->info['chunk']['key'])){
|
|
throw new Exception('分片密钥错误');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 获取文件后缀名
|
|
* @param $filename
|
|
* @return string
|
|
*/
|
|
protected function getFileExt($filename): string
|
|
{
|
|
return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
}
|
|
|
|
/**
|
|
* 获取随机文件名
|
|
* @param int $length
|
|
* @return string
|
|
*/
|
|
protected function getRandomKey(int $length = 16): string
|
|
{
|
|
$charTable = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
$result = "";
|
|
for ( $i = 0; $i < $length; $i++ ){
|
|
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 获取上传目录
|
|
* @param $key
|
|
* @return string|string[]
|
|
*/
|
|
protected function getPath($key)
|
|
{
|
|
// 目录分割
|
|
$ds = DIRECTORY_SEPARATOR;
|
|
|
|
// 配置目录
|
|
$save_dir = str_replace('/',$ds,$this->policy['config']['save_dir']);
|
|
|
|
// 根目录
|
|
$root_path = realpath(env('root_path') . './public') . $save_dir;
|
|
|
|
// 临时存储目录
|
|
$temp_path = realpath(env('root_path') . './public') . str_replace('/',$ds,'/temp/');
|
|
|
|
// 当前保存目录
|
|
$file_path = date('Ymd') . $ds . $this->uid . $ds;
|
|
|
|
//文件名
|
|
$file_name = uniqid( "file_") . time();
|
|
|
|
$data = [
|
|
'root' => $root_path,
|
|
'temp' => $temp_path,
|
|
'file' => $file_path,
|
|
'path' => $root_path . $file_path,
|
|
'temp_path' => $temp_path . $file_path,
|
|
'name' => $file_name,
|
|
'filename' => $file_name .'.'. $this->getFileExt($this->info['file']['name'])
|
|
];
|
|
|
|
if($key == 'all'){
|
|
return $data;
|
|
}
|
|
|
|
return $data[$key] ?? '';
|
|
}
|
|
|
|
|
|
public function upload(){
|
|
// 超时时间5分钟
|
|
@set_time_limit(5 * 60);
|
|
|
|
// 获取有效的目录ID
|
|
$this->info['file']['folder'] = FileManage::getFolderAllowPid(input('post.folder_id',0),$this->uid);
|
|
|
|
// 获取上传文件大小
|
|
$this->info['file']['size'] = input('post.size',0);
|
|
|
|
// 获取上传文件名
|
|
$this->info['file']['name'] = input('post.name','');
|
|
|
|
// 上传文件对象获取
|
|
$this->info['file']['data'] = request()->file('file');
|
|
|
|
// 分片上传
|
|
$this->info['chunk']['key'] = input('post.chunks_key');
|
|
$this->info['chunk']['chunk'] = input('post.chunk',0);
|
|
$this->info['chunk']['chunks'] = input('post.chunks',0);
|
|
|
|
$this->info['uid'] = $this->uid;
|
|
|
|
// 参数校验
|
|
$this->check();
|
|
|
|
// 目录
|
|
$path = $this->getPath('all');
|
|
|
|
// 上传驱动
|
|
switch ($this->policy['type']){
|
|
// 阿里云
|
|
case 'aliyunoss':
|
|
$upload = new AliyunOss($this->info,$this->policy,$path);
|
|
break;
|
|
// 腾讯云
|
|
case 'txyunoss':
|
|
$upload = new TxyunOss($this->info,$this->policy,$path);
|
|
break;
|
|
// 本地
|
|
default:
|
|
$upload = new Local($this->info,$this->policy,$path);
|
|
break;
|
|
}
|
|
|
|
// 上传文件
|
|
$file_object = $upload->upload();
|
|
|
|
// 插入数据库
|
|
if($file_object != 'chunk_file' && $file_object != null){
|
|
// 加入数据库
|
|
$data = [
|
|
'uid' => $this->uid,
|
|
'origin_name' => $this->info['file']['name'],
|
|
'file_name' => $file_object,
|
|
'size' => $this->info['file']['size'],
|
|
'ext' => $this->getFileExt($this->info['file']['name']),
|
|
'parent_folder' => $this->info['file']['folder'],
|
|
'policy_id' => $this->policy['id'],
|
|
'create_time' => time(),
|
|
'update_time' => time()
|
|
];
|
|
|
|
$file_id = (new Stores)->insertGetId($data);
|
|
|
|
$share_id = Shares::addShare($this->uid,$file_id,0);
|
|
|
|
Stores::where('id',$file_id)->update(['shares_id' => $share_id]);
|
|
|
|
return ['code' => 1,'msg' => '文件上传成功'];
|
|
}
|
|
|
|
return ['code' => 1,'chunks' => 'chunk 文件上传成功'];
|
|
}
|
|
|
|
} |