config = [ 'disks' => [ 'local' => [ 'driver' => LocalDriver::class, //上传类 'save_dir' => app()->getRootPath() . 'public/attachment', //上传保存路径 'file_path' => '/attachment', //上传保存路径 'tmp_dir' => root_path('runtime' . DIRECTORY_SEPARATOR . 'uploadtmp'),//临时目录 'slice_first' => 0, //从第几片开始 ], //继续添加其它仓库 ], 'default' => [ 'disk' => 'local', //默认磁盘 'extensions' => 'jpg,png,mp4', //后缀 'mimeTypes' => 'image/*,video/*', //类型 'middlewares' => [], //中间件数组 'maxSize' => 1 * 1024 * 1024, //单包最大上传大小 2M ] ]; } /**文件上传 * @param $data * @param $file * @return array */ public function uploadFile($data, $file) { if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { exit; // finish preflight CORS requests here } try { //处理部分数据 $data['size'] = $file->getSize(); $data['name'] = $file->getOriginalName(); $data['ext'] = $file->extension(); //检测文件大小 if (!$this->checkSize($data['size'])) { $this->_error = "超出文件上传大小限制"; return ['code' => -1, 'data' => []]; } $config = $this->config; $uploadManager = new UploadManager($config); $fileInfo = new FileInfo(); $fileInfo->identifier = $data['hash']; $fileInfo->filename = $data['name']; $fileInfo->chunkNumber = $data['chunk'] ?? 0;; $fileInfo->chunkNumber = intval($fileInfo->chunkNumber ?? 0); //未设置分片数量 则默认总数为1 当前为0 $fileInfo->totalChunks = $data['chunks'] ?? 1; $fileInfo->totalChunks = intval($fileInfo->totalChunks ?? 1); $fileInfo->totalChunks = ($fileInfo->totalChunks > 0) ? $fileInfo->totalChunks : 1; $fileInfo->totalSize = $data['size']; //获取后缀 $fileInfo->ext = $data['ext']; if (!$this->checkFileType($fileInfo->ext)) { $this->_error = "禁止上传的文件类型"; return ['code' => -1, 'data' => []]; } $upload = $uploadManager->uploadFile($fileInfo); //如果文件较小 直接上传完成 if (isset($upload['savepath']) && $upload['code'] == 0) { $upload = $this->buildFileUrl($upload); return ['code' => 1, 'data' => $upload, 'msg' => '成功']; } $check = $uploadManager->checkFile($fileInfo); //如果上传完成 if (isset($check['savepath']) && $check['code'] == 0) { $check = $this->buildFileUrl($check); return ['code' => 1, 'data' => $check]; } else { $this->_error = "文件包不完整"; return ['code' => 0, 'data' => $check]; } } catch (\Exception $e) { $this->_error = $e->getMessage(); return ['code' => -1, 'data' => $e->getMessage()]; } } /** * 处理文件 * 扩展包存在问题 ,考虑后续更新 尽量不更改扩展包,在这里做文件的处理 */ public function buildFileUrl($data) { if (isset($data['savepath']) && $data['savepath'] != '') { $conf = $this->config; //获取除域名外的文件路径 $save_dir = $conf['disks'][$conf['default']['disk']]['save_dir']; $file_path = str_replace($save_dir, '', $data['savepath']); //拼接域名 $data['save_path'] = $conf['disks'][$conf['default']['disk']]['file_path'] . $file_path; $data['file_path'] = $this->domain . $data['save_path']; //删除多余的信息 unset($data['savepath']); unset($data['code']); } return $data; } //检测文件上传大小 public function checkSize($file_size) { if ($file_size > $this->config['default']['maxSize']) { return false; } return true; } /**检测文件类型 * @param $file_ext * @return array|bool */ public function checkFileType($file_ext) { //获取配置信息 $extensions = $this->config['default']['extensions']; //为空或者为 * 表示不过滤 if ($extensions == "" || $extensions == '*') { return true; } //字符转换成数组 $exts = explode(',', $extensions); if (in_array($file_ext, $exts)) { $this->_error = "禁止上传该类型文件"; return ['code' => 0, 'data' => '']; } return true; } /** * 检测文件分片情况 */ public function checkFile($hash,$count){ $filePath = $this->config['disks'][$this->config['default']['disk']]['tmp_dir'] . $hash; //临时分片文件路径 // dump($filePath); //检查分片是否存在 $chunkExists = []; for ($index = 0; $index < $count; $index++) { if (file_exists("{$filePath}_{$index}")) { array_push($chunkExists, $index); } } //分片有缺失,返回已存在的分片 $res['uploaded'] = $chunkExists; return $res; } /** * 删除文件 * @param $path */ public function deleteFile($path){ $path = app()->getRootPath() . 'public'.$path; if (file_exists($path)){ @unlink($path); } return true; } /** * 返回报错 * @return string */ public function getError() { return $this->_error; } }