getClientOriginalExtension()); if (!in_array($extension, ['doc', 'docx'])) { throw new \InvalidArgumentException('文件格式不支持,请上传 Word 文档(.doc 或 .docx)'); } // 验证专用文档必须有分组 if ($type === 'dedicated' && empty($groupId)) { throw new \InvalidArgumentException('专用知识库文档必须指定所属分组'); } // 使用事务确保一致性 return DB::transaction(function () use ($file, $title, $type, $groupId, $uploaderId) { // 获取原始文件名 $originalFileName = $file->getClientOriginalName(); // 生成文件存储路径,使用原始文件名 $directory = 'documents/' . date('Y/m/d'); $filePath = $file->storeAs($directory, $originalFileName, 'local'); // 创建数据库记录,设置初始转换状态为 pending $document = Document::create([ 'title' => $title, 'file_path' => $filePath, 'file_name' => $originalFileName, 'file_size' => $file->getSize(), 'mime_type' => $file->getMimeType(), 'type' => $type, 'group_id' => $groupId, 'uploaded_by' => $uploaderId, 'description' => '', 'conversion_status' => 'pending', ]); // 文档保存成功后,触发异步转换 $conversionService = app(DocumentConversionService::class); $conversionService->queueConversion($document); return $document; }); } /** * 验证用户是否有权访问指定文档 * * @param Document $document 要访问的文档 * @param User $user 用户 * @return bool */ public function validateDocumentAccess(Document $document, User $user): bool { // 如果是全局文档,所有用户都可以访问 if ($document->type === 'global') { return true; } // 如果是专用文档,检查用户是否属于该文档的分组 if ($document->type === 'dedicated') { // 获取用户所属的所有分组 ID $userGroupIds = $user->groups()->pluck('groups.id')->toArray(); // 检查文档的分组 ID 是否在用户的分组列表中 return in_array($document->group_id, $userGroupIds); } return false; } /** * 下载文档 * * @param Document $document 要下载的文档 * @param User $user 用户 * @return StreamedResponse * @throws \Exception */ public function downloadDocument(Document $document, User $user): StreamedResponse { // 验证用户权限 if (!$this->validateDocumentAccess($document, $user)) { throw new \Exception('您没有权限访问此文档'); } // 检查文件是否存在 if (!Storage::disk('local')->exists($document->file_path)) { throw new \Exception('文档不存在或已被删除'); } // 返回文件流式响应,使用原始文件名 return Storage::disk('local')->download( $document->file_path, $document->file_name ); } /** * 记录文档下载日志 * * @param Document $document 被下载的文档 * @param User $user 下载的用户 * @param string|null $ipAddress IP 地址 * @return DownloadLog */ public function logDownload(Document $document, User $user, ?string $ipAddress = null): DownloadLog { return DownloadLog::create([ 'document_id' => $document->id, 'user_id' => $user->id, 'downloaded_at' => now(), 'ip_address' => $ipAddress ?? request()->ip(), ]); } }