service = $service; } #[OA\Get( path: '/files', summary: '列表', tags: ['附件管理'], x: [ SchemaConstants::X_SCHEMA_REQUEST => UploadQueryRequest::class, ] )] #[Permission(code: 'upload:files:list')] #[PageResponse(schema: UploadResponse::class, example: [])] public function index(Request $request): \support\Response { return parent::index($request); } #[OA\Get( path: '/files/{id}', summary: '详情', tags: ['附件管理'], x: [ SchemaConstants::X_PROPERTY_IN => 'id', SchemaConstants::X_SCHEMA_REQUEST => IdRequest::class, ] )] #[Permission(code: 'upload:files:read')] #[SimpleResponse(schema: UploadResponse::class, example: [])] public function show(Request $request): \support\Response { return parent::show($request); } #[OA\Delete( path: '/files/{id}', summary: '删除', tags: ['附件管理'], x: [ SchemaConstants::X_PROPERTY_IN => 'id', SchemaConstants::X_SCHEMA_REQUEST => IdRequest::class, ] )] #[Permission(code: 'upload:files:delete')] #[SimpleResponse(schema: [], example: [])] public function destroy(Request $request): \support\Response { return parent::destroy($request); } #[OA\Delete( path: '/files', summary: '批量删除', tags: ['附件管理'], x: [ SchemaConstants::X_SCHEMA_REQUEST => BatchDeleteRequest::class, ] )] #[Permission(code: 'upload:files:delete')] #[SimpleResponse(schema: [], example: [])] public function batchDelete(Request $request): \support\Response { return parent::destroy($request); } #[OA\Post( path: '/files/fetch-and-save-image', summary: '上传网络图片到服务器', tags: ['附件管理'], )] #[RequestBody( required: true, content: new OA\JsonContent( properties: [ new OA\Property( property: 'url', description: '图片URL', type: 'string', example: 'https://example.com/image.jpg' ), ] ) )] #[Permission(code: 'upload:files:fetch_and_save_image')] #[SimpleResponse(schema: [], example: [])] public function downloadNetworkImage(Request $request): \support\Response { $url = $request->input('url', ''); $result = $this->service->saveNetworkImage($url); return Json::success('操作成功', $result); } #[OA\Get( path: '/files/download-by-id/{id}', summary: '根据ID下载资源', tags: ['附件管理'], parameters: [ new OA\Parameter( name: 'id', description: '文件ID', in: 'path', required: true, schema: new OA\Schema(type: 'string', example: '123456789012345678') ), ] )] #[Permission(code: 'upload:files:download_by_id')] #[SimpleResponse(schema: [], example: [])] public function downloadResourceById(Request $request): \support\Response|\Webman\Http\Response { try { $id = $request->route->param('id'); $data = $this->service->get($id); if (empty($data)) { throw new AdminException('数据未找到', ['errorCode' => -1]); } return response()->download($data->path, $data->filename); } catch (\Throwable $e) { return Json::fail($e->getMessage(), [], $e->getCode()); } } #[OA\Get( path: '/files/download-by-hash/{hash}', summary: '根据hash下载资源', tags: ['附件管理'], parameters: [ new OA\Parameter( name: 'hash', description: '文件Hash', in: 'path', required: true, schema: new OA\Schema(type: 'string', example: '123456789012345678') ), ] )] #[Permission(code: 'upload:files:download_by_hash')] #[SimpleResponse(schema: [], example: [])] public function downloadResourceByHash(Request $request): \support\Response|\Webman\Http\Response { try { $hash = $request->route->param('hash'); $data = $this->service->get(['hash' => $hash]); if (empty($data)) { throw new AdminException('数据未找到', ['errorCode' => -1]); } return response()->download($data->path, $data->filename); } catch (\Throwable $e) { return Json::fail($e->getMessage(), [], $e->getCode()); } } /** * @throws \Throwable */ #[OA\Post( path: '/files/upload-image', summary: '上传图片', tags: ['附件管理'], )] #[Permission(code: 'upload:files:upload_image')] #[RequestBody( required: true, content: new OA\MediaType( mediaType: 'multipart/form-data', schema: new OA\Schema( properties: [ new OA\Property( property: 'file', description: '文件', type: 'string', format: 'binary' ), new OA\Property( property: 'sub_dir', description: '子目录路径,例如:image/202603', type: 'string', example: 'image/202603' ), ] ) ) )] #[SimpleResponse(schema: UploadResponse::class, example: [])] public function uploadImage(Request $request): \support\Response { try { $subDir = $request->input('sub_dir', 'image'); $subDir .= '/' . date('Ym'); $result = $this->service->upload($subDir); return Json::success('ok', $result->toArray()); } catch (\Exception $e) { return Json::fail($e->getMessage()); } } #[OA\Post( path: '/files/upload-file', summary: '上传文件', tags: ['附件管理'], )] #[Permission(code: 'upload:files:upload_file')] #[RequestBody( required: true, content: new OA\MediaType( mediaType: 'multipart/form-data', schema: new OA\Schema( properties: [ new OA\Property( property: 'file', description: '文件', type: 'string', format: 'binary' ), new OA\Property( property: 'sub_dir', description: '子目录路径,例如:file/202603', type: 'string', example: 'file/202603' ), ] ) ) )] #[SimpleResponse(schema: UploadResponse::class, example: [])] public function uploadFile(Request $request): \support\Response { try { $subDir = $request->input('sub_dir', 'file'); $subDir .= '/' . date('Ym'); $result = $this->service->upload($subDir); return Json::success('ok', $result); } catch (\Exception $e) { return Json::fail($e->getMessage()); } } #[OA\Post( path: '/files/svg-icons', summary: 'SVG图标列表', tags: ['附件管理'], )] #[Permission(code: 'upload:files:upload_file')] #[SimpleResponse(schema: [], example: [])] public function svgIcons(Request $request): \support\Response { try { $targetDir = public_path() . '/upload/svg-icons'; if (!is_dir($targetDir)) { return Json::success('ok', []); } $icons = []; foreach (glob($targetDir . '/*.svg') ?: [] as $file) { $name = pathinfo($file, PATHINFO_FILENAME); $content = file_get_contents($file); if ($content === false) { continue; } $icons[] = [ 'icon' => 'svg:' . $name, 'name' => $name, 'filename' => basename($file), 'url' => '/upload/svg-icons/' . basename($file), 'content' => $content, ]; } return Json::success('ok', $icons); } catch (\Exception $e) { return Json::fail($e->getMessage()); } } #[OA\Post( path: '/files/upload-svg-icon', summary: '上传SVG图标', tags: ['附件管理'], )] #[Permission(code: 'upload:files:upload_file')] #[RequestBody( required: true, content: new OA\MediaType( mediaType: 'multipart/form-data', schema: new OA\Schema( properties: [ new OA\Property( property: 'file', description: 'SVG图标文件', type: 'string', format: 'binary' ), ] ) ) )] #[SimpleResponse(schema: [], example: [])] public function uploadSvgIcon(Request $request): \support\Response { try { $file = $request->file('file'); if (!$file) { return Json::fail('请选择SVG文件'); } if ($file->getSize() > 512 * 1024) { return Json::fail('SVG文件大小不能超过512KB'); } $extension = strtolower($file->getUploadExtension()); $mime = $file->getUploadMimeType(); $allowedMimeTypes = ['image/svg+xml', 'image/svg', 'text/xml', 'application/xml', 'text/plain', '']; if ($extension !== 'svg' || !in_array($mime, $allowedMimeTypes, true)) { return Json::fail('只支持SVG格式文件'); } $content = file_get_contents($file->getPathname()); if ($content === false || trim($content) === '') { return Json::fail('SVG文件读取失败'); } if (!preg_match('/]/i', $content)) { return Json::fail('请选择有效的SVG文件'); } if (preg_match('/getUploadName(), PATHINFO_FILENAME); $iconName = preg_replace('/[^a-zA-Z0-9_-]/', '-', $originalName) ?: 'icon'; $iconName = trim($iconName, '-_') ?: 'icon'; $targetDir = public_path() . '/upload/svg-icons'; if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true) && !is_dir($targetDir)) { return Json::fail('SVG图标目录创建失败'); } $targetPath = $targetDir . '/' . $iconName . '.svg'; if (is_file($targetPath)) { $iconName .= '-' . date('YmdHis'); $targetPath = $targetDir . '/' . $iconName . '.svg'; } if (file_put_contents($targetPath, $content, LOCK_EX) === false) { return Json::fail('SVG图标保存失败'); } return Json::success('上传成功', [ 'icon' => 'svg:' . $iconName, 'name' => $iconName, 'filename' => $iconName . '.svg', 'url' => '/upload/svg-icons/' . $iconName . '.svg', 'path' => str_replace('\\', '/', $targetPath), 'content' => $content, ]); } catch (\Exception $e) { return Json::fail($e->getMessage()); } } /** * 上传图片返回base64 * 用于插件开发等需要base64预览的场景 */ #[OA\Post( path: '/files/upload-image-base64', summary: '上传图片返回base64', tags: ['附件管理'], )] #[Permission(code: 'upload:files:upload_image_base64')] #[RequestBody( required: true, content: new OA\JsonContent( properties: [ new OA\Property( property: 'file', description: '图片文件', type: 'string', format: 'binary' ), ] ) )] public function uploadImageBase64(Request $request): \support\Response { try { $file = $request->file('file'); if (!$file) { return Json::fail('请选择图片文件'); } // 验证文件类型 $allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']; if (!in_array($file->getUploadMimeType(), $allowedTypes)) { return Json::fail('只支持PNG、JPEG、JPG、GIF格式的图片'); } // 验证文件大小(最大2MB) $maxSize = 2 * 1024 * 1024; if ($file->getSize() > $maxSize) { return Json::fail('图片大小不能超过2MB'); } // 读取文件内容并转换为base64 $imageData = file_get_contents($file->getPathname()); if ($imageData === false) { return Json::fail('图片读取失败'); } $base64 = 'data:' . $file->getUploadMimeType() . ';base64,' . base64_encode($imageData); return Json::success('上传成功', [ 'base64' => $base64, 'size' => $file->getSize(), 'mime' => $file->getUploadMimeType(), ]); } catch (\Exception $e) { return Json::fail($e->getMessage()); } } #[OA\Get( path: '/export/download-excel', summary: '下载导出的excel',//下载导出的excel-后期需要优化实现下载成功后删除原文件 tags: ['附件管理'], )] #[Permission(code: 'upload:files:download_excel')] public function downloadExcel(Request $request): ?\support\Response { $param = $request->all(); $file = $param['file_path'];//文件路径 $downloadName = $param['file'] ?? date('Y-m-d His', time());//文件下载名称 $filePath = runtime_path() . $file; //生成的文件5分钟后超时自动删除 $queue = 'remove-excel-file'; Client::send($queue, $param, 300); return response()->download($filePath, $downloadName); } #[OA\Post( path: '/files/common/wangeditor', summary: '适配wangeditor编辑器上传接口', tags: ['附件管理'], )] #[Permission(code: 'upload:files:wangeditor')] public function wangeditor(Request $request): \support\Response { try { $subDir = $request->input('sub_dir', 'image'); $subDir .= '/' . date('Ym'); $result = $this->service->upload($subDir); $data = $result->toArray(); $data['url'] = $data['base_path'] ?? ''; return Json(['errno' => 0, 'data' => $data]); } catch (\Exception $e) { return Json([ 'errno' => 1, 'message' => $e->getMessage(), ]); } } }