DIRECTORY_SEPARATOR = DIRECTORY_SEPARATOR == "\\" ? "/" : DIRECTORY_SEPARATOR; } /** * 删除 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function del(): Json { if ($this->request->isPost()) { $ids = input('post.ids/a', []); if (empty($ids)) { $ids[] = input('post.id/d'); } $items = AttachmentModel::whereIn('id', $ids)->where('is_dir', AttachmentModel::COMMON_ON)->select(); if ($items->where('is_dir', AttachmentModel::COMMON_ON)->count()) { $dirPaths = []; foreach ($items->toArray() as $item) { $dirPaths[] = $item['path'].$item['name']. $this->DIRECTORY_SEPARATOR ; } if (AttachmentModel::where('path', 'in', $dirPaths)->count()) { return $this->json(4001, '待删除目录下存在内容!'); } } AttachmentModel::deleteByIds($ids); // Log::write(get_class().'Del', 'del', '涉及到的ID为:'.implode(',', $ids)); return $this->json(); } return $this->json(4001, '非法请求!'); } /** * 单个字段编辑 * * @return Json * @throws Exception */ public function modify(): Json { if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'field' => 'require', 'value' => 'require', ]); if ($validate !== true) { return $validate; } if (!$info = AttachmentModel::findById($item['id'])) { return $this->json(4001, '记录不存在'); } if ($item['field'] == 'name' && $info['is_dir'] == AttachmentModel::COMMON_ON) { return $this->json(4002, '目录名称不能修改'); } $update = [$item['field'] => $item['value']]; try { $info->save($update); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } return $this->json(4000, '非法请求'); } /** * 添加 * * @return Json|View * @throws Exception */ public function add() { if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'title|合集标题' => 'require', 'user|虚拟用户' => 'require', 'headimg|虚拟用户头像' => 'require', ]); if ($validate !== true) { return $validate; } try { $now = date('Y-m-d H:i:s'); $item['created_at'] = $now; $item['created_by'] = $this->auth['user_id']; AttachmentModel::create($item); return $this->json(); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } return $this->view(); } /** * 添加文件夹 * * @return Json|View * @throws Exception */ public function addFolder() { if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'name|文件夹名称' => 'require|alphaDash|max:20', 'path|文件路径' => 'require', ]); // 例 name=dir4 path=/storage/dir1/dir2/dir3 // 去首尾/ $path = trim($item['path'], $this->DIRECTORY_SEPARATOR ); // 全路径 如 /storage/dir1/dir2/dir3/dir4/ 注意前后都有/ $fullPath = $this->DIRECTORY_SEPARATOR .$path. $this->DIRECTORY_SEPARATOR .$item['name']. $this->DIRECTORY_SEPARATOR ; if ($validate !== true) { return $validate; } AttachmentModel::pathDirHandle($fullPath); return $this->json(); } $path = input('path/s', AttachmentModel::ROOT_PATH); $this->data['path'] = $path; return $this->view(); } /** * 图片列表 * * @return View|Json * @throws Exception */ public function image() { $path = input('post.path', AttachmentModel::ROOT_PATH); $path = $this->DIRECTORY_SEPARATOR . trim($path, $this->DIRECTORY_SEPARATOR). $this->DIRECTORY_SEPARATOR; $path = str_replace("\\","/",$path); $type = input('type/s', 'image'); $selected = input('selected', false); $multiple = input('multiple', false); Config::load('extra/alioss', 'alioss'); $config = config('alioss'); $oss = $config['customDomain']; if ($this->request->isPost()) { $items = $this->list($path, ['image']); return $this->json(0, '操作成功', $items); } $this->data['path'] = $path; $this->data['oss'] = $oss; $this->data['type'] = $type; $this->data['multiple'] = $multiple; $this->data['selected'] = $selected; return $this->view(); } /** * 视频列表 * * @return View|Json * @throws Exception */ public function video() { $path = input('post.path', AttachmentModel::ROOT_PATH); $path = $this->DIRECTORY_SEPARATOR . trim($path, $this->DIRECTORY_SEPARATOR ) . $this->DIRECTORY_SEPARATOR ; $path = str_replace("\\","/",$path); $type = input('type/s', 'video'); $selected = input('selected', false); $multiple = input('multiple', false); Config::load('extra/alioss', 'alioss'); $config = config('alioss'); $oss = $config['customDomain']; if ($this->request->isPost()) { $items = $this->list($path, ['video']); return $this->json(0, '操作成功', $items); } $this->data['path'] = $path; $this->data['oss'] = $oss; $this->data['type'] = $type; $this->data['multiple'] = $multiple; $this->data['selected'] = $selected; return $this->view(); } /** * 文件列表 * * @return View|Json * @throws Exception */ public function file() { Config::load('extra/alioss', 'alioss'); $config = config('alioss'); $oss = $config['customDomain']; $type = input('type/s', 'all'); $selected = input('selected', false); $multiple = input('multiple', false); if ($this->request->isPost()) { $page = input('post.page', 1); $size = input('post.size', 20); $searchParams = input('searchParams'); $where = []; if ($searchParams) { foreach ($searchParams as $key => $param) { if (!empty($param)) { if (is_string($param)) { if ($key == 'is_oss') { if ($param >= 0) { $where[] = ['is_oss', '=', $param]; } } else { $where[] = [$key, 'like', '%'.$param.'%']; } } elseif (is_array($param)) { //数组空元素去除 foreach ($param as $k => $val) { if (empty($val)) { unset($param[$k]); } } if (!empty($param)) { $where[] = [$key, 'in', $param]; } } } } } if ($type !== 'all') { $where[] = ['type', '=', $type]; } $items = AttachmentModel::findList($where, [], $page, $size, function ($q) { return $q->where('type', '<>', 'dir')->order('updated_at', 'desc'); }); $items['list']->each(function ($item) { $item->size_text = getFilesize($item['size'] ?? 0); }); return $this->json(0, '操作成功', $items); } $this->data['oss'] = $oss; $this->data['type'] = $type; $this->data['multiple'] = $multiple; $this->data['selected'] = $selected; return $this->view(); } /** * 一键删除失效记录 即oss不存在&&本地不存在 * * @return Json */ public function delLostFile(): Json { if ($this->request->isPost()) { $total = AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) ->where('is_dir', AttachmentModel::COMMON_OFF) ->where('is_oss', AttachmentModel::COMMON_OFF) ->where('has_local', AttachmentModel::COMMON_OFF) ->count(); if ($total === 0) { return $this->json(0, 'success', ['total' => $total]); } if (AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) ->where('is_dir', AttachmentModel::COMMON_OFF) ->where('is_oss', AttachmentModel::COMMON_OFF) ->where('has_local', AttachmentModel::COMMON_OFF) ->delete()) { return $this->json(0, 'success', ['total' => $total]); } return $this->json(4004, '删除失败'); } return $this->json(4000, '请求错误'); } /** * 一键上传本地文件到OSS * * @return Json */ public function toOss(): Json { if ($this->request->isPost()) { Config::load('extra/alioss', 'alioss'); $config = config('alioss'); $ossObject = AliOss::instance(); $bucket = $config['bucket']; $total = AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) ->where('is_dir', AttachmentModel::COMMON_OFF) ->where('is_oss', AttachmentModel::COMMON_OFF) ->field('id') ->count(); $done = 0; $none = 0; if ($total === 0) { return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); } try { AttachmentModel::where('type', '<>', AttachmentModel::TYPE_DIR) ->where('is_dir', AttachmentModel::COMMON_OFF) ->where('is_oss', AttachmentModel::COMMON_OFF) ->field('id,src') ->chunk(3, function ($items) use ($ossObject, $bucket, &$done, &$none) { $doneIds = []; $noneIds = []; foreach ($items as $item) { if ($item['src']) { $realPath = public_path().ltrim($item['src'], $this->DIRECTORY_SEPARATOR ); if (!file_exists($realPath)) { $none++; $noneIds[] = $item['id']; continue; } $pathInfo = pathinfo($item['src']); $object = ltrim($item['src'], $this->DIRECTORY_SEPARATOR ); //是否存在 if (!$ossObject->doesObjectExist($bucket, $object)) { //创建目录 $ossObject->createObjectDir($bucket, ltrim($pathInfo['dirname'], $this->DIRECTORY_SEPARATOR )); $ossObject->uploadFile($bucket, $object, $realPath); } $doneIds[] = $item['id']; $done++; } } // 失效标记 if ($noneIds) { $update = ['is_oss' => AttachmentModel::COMMON_OFF, 'has_local' => AttachmentModel::COMMON_OFF]; (new AttachmentModel())->where('id', 'in', $noneIds)->update($update); } // 完成标记 if ($doneIds) { $update = ['is_oss' => AttachmentModel::COMMON_ON]; (new AttachmentModel())->where('id', 'in', $doneIds)->update($update); } }); return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); } catch (Exception $e) { \think\facade\Log::error('本地文件一键上传OSS失败 '.$e->getMessage()); return $this->json(0, 'success', ['total' => $total, 'done' => $done, 'none' => $none]); } } } /** * 指定类型附件列表 * * @param array $type * @param string $path * @return array * @throws Exception */ protected function list(string $path, array $type): array { $type[] = 'dir'; $where[] = ['path', '=', $path]; $where[] = ['type', 'in', $type]; $items = AttachmentModel::findList($where, [], 1, 0, function ($q) { return $q->order('is_dir', 'desc')->order('updated_at', 'desc'); }); $items['list']->each(function ($item) { $item->size_text = getFilesize($item['size'] ?? 0); }); $items['path'] = $path; return $items; } /** * 获取文件大小 * * @return Json */ public function getSize(): Json { $path = input('post.path', ''); $types = input('post.type/a', []); $size = ''; if (empty($path)) { return $this->json(0, '操作成功', $size); } $path = str_replace("\\","/",$path); $total = AttachmentModel::where('path', 'like', $path.'%') ->when(!empty($types), function ($q) use ($types) { $q->where('type', 'in', $types); }) ->sum('size'); return $this->json(0, '操作成功', getFilesize($total)); } // 将没有md5的文件 更新md5 仅针对本地文件 public function md5List() { $noMd5List = AttachmentModel::whereNull('md5')->select(); $update = []; foreach ($noMd5List as $item) { try { if (!empty($item['src'])) { $arr = []; $path = public_path().ltrim($item['src'], $this->DIRECTORY_SEPARATOR ); $file = new \think\File($path); $arr['md5'] = $file->md5(); $arr['id'] = $item['id']; $update[] = $arr; } } catch (Exception $e) { continue; } } (new AttachmentModel())->saveAll($update); } }