分片上传(说明)
1、 使用时 $this->end(上传完成标识,0未上传完成 1上传完成,进行分片合并生成文件),紧跟最后一片分片数据, 要上传的目录和移动目录根据实际情况进行替换
2、mkdir() 函数指定的目次权限只能小于即是体系umask设定的默许权限。如linux默许的umask平常0022, 即建立目次的默许权限是0755, 所以这时候php mkdir(’./aa/’,0777) 获得目次的权限是0755.
3、 chmod() 函数不受体系umask影响,能够设置比体系默许权限大的权限。
class UploadFiles
{
/**
* 构造函数
*/
public function __construct()
{
$this->end=input('end'); //上传完成标识
$this->name=input('device_name'); //目标文件夹
$this->chunkid=input('chunkid');//分片上传标标识,同一个文件分片时,标识相同
$this->chunkcount=input('chunkcount');//分片总数量
$this->chunkindex=input('chunkindex');//当前第几片
$this->extension=input('extension');//文件后缀名
$this->extension=='jpg'?$this->type='img':$this->type='video';//目标文件夹
$this->basePath=config('filesystem.disks.public.root') . DIRECTORY_SEPARATOR;//基础路径
}
/**
* 上传文件
* step 1 检测切片
* step 2 合并切片
* step 3 移动文件
*/
function uploadImg($pathTmp)
{
try {
$pathTmp=$pathTmp.'/'.$this->name;
// 获取表单上传文件
$files = request()->file();
//验证文件
validate(['image' => 'filesize:10240|fileExt:[AVI,wmv,MPEG,QuickTime,RealVideo,Flash,Mpeg-4,mov,rmvb,rm,FLV,mp4,3GP]'])->check($files);
//获取文件
$file=$files['files'];
$fileName=time().'.'.$this->extension;
//判断是否是切片上传
if($this->chunkid){
//缓存文件
$fileName = $this->chunkid . "-" . $this->chunkindex . '.tmp';
$this->type='tmp';
}
//根据上传文件类型进行文件夹创建
$root = $pathTmp . '/'.$this->type;
//上传文件
$savename= Filesystem::disk('public')->putFileAs($root, $file, $fileName);
//缓存文件存放路径
$filePath = $this->basePath . $root . DIRECTORY_SEPARATOR;
//上传完毕检测文件状态
if($this->end){
$this->check_file($filePath);
}
if ($this->end==1) {
//合并文件
$this->mearge_files($filePath);
//移动文件
$savename= $this->move_file($pathTmp);
}
return ['shortName'=>$savename,'longNmame'=>request()->domain() . '/storage/' .$savename];
} catch (ValidateException $e) {
echo $e->getMessage();
}
}
}
检测切片完整性
/**
* 检测切片完整
* @param $filePath
* @throws \Exception
*/
public function check_file($filePath){
//检查所有分片是否都存在
for ($i = 0; $i < $this->chunkcount; $i++) {
if (!file_exists("{$filePath}{$this->chunkid}-{$i}.tmp")) {
throw new \Exception("分片文件缺失!");
}
}
}
合成文件后删除分片
/**
* 合并分片并删除
* @param $filePath 缓存文件存放路径
* @throws \Exception
*/
public function mearge_files($filePath){
if (!$destFile = @fopen($filePath . $this->chunkid . '.' . $this->extension, "wb")) {
throw new \Exception("分片上传文件错误.");
}
if (flock($destFile, LOCK_EX)) { // 进行排他型锁定
for ($i = 0; $i < $this->chunkcount; $i++) {
$partFile = "{$filePath}{$this->chunkid}-{$i}.tmp";
if (!$handle = @fopen($partFile, "rb")) {
break;
}
while ($buff = fread($handle, filesize($partFile))) {
fwrite($destFile, $buff);
}
@fclose($handle);
@unlink($partFile); //删除分片
}
flock($destFile, LOCK_UN);
}
@fclose($destFile);
}
移动合成后的文件到指定目录
/**
* 移动切片合成后的图片到目标文件夹
* @param $root
* @return string
*/
public function move_file($root){
//文件夹类型
$this->extension=='jpg'?$this->type='img':$this->type='video';
//生成的新文件名
$newFileName=time().'.'.$this->extension;
//基础目录
$basePath=$this->basePath . str_replace(DIRECTORY_SEPARATOR, '/', $root) . DIRECTORY_SEPARATOR;
//缓存合并后生成的文件
$oldFile= $basePath.'tmp/'.$this->chunkid.'.'.$this->extension;
//目标文件夹
$targetPath=$basePath . '/'.$this->type;
//检测目标文件夹是否存在,不存在则创建
if(!file_exists($targetPath)){
mkdir($targetPath,0777,true);
}
$newFile=$targetPath.'/'.$newFileName;
//移动文件
rename($oldFile,$newFile);
return $root.'/'.$this->type.'/'.$newFileName;
}