getMimeType($filePath, $extension); $size = filesize($filePath) ?: 0; $sceneUrl = $scene ? ($scene . '/') : ''; $dir = config('oss.oss_main_dir') . $sceneUrl . date('Ymd') . '/'; // 使用传入的 original_name 命名(缺少扩展名时补上推断的扩展名),并做简单安全处理 $safeBaseName = preg_replace('/[\\\\\/]+/', '_', $originalName); if ($extension && strtolower(pathinfo($safeBaseName, PATHINFO_EXTENSION)) !== strtolower($extension)) { // 若提供的名称没有扩展名或扩展名不一致,则以推断扩展名为准 $safeBaseName = pathinfo($safeBaseName, PATHINFO_FILENAME) . '.' . $extension; } elseif (!$extension && !pathinfo($safeBaseName, PATHINFO_EXTENSION)) { // 实在没有扩展名信息时,保持原名 } // 重名检测:同一目录、同名且同类型则在文件名后追加序号 $uploadedFilesService = new UploadedFilesService(); $candidateName = $safeBaseName; $nameBody = pathinfo($safeBaseName, PATHINFO_FILENAME); $nameExt = pathinfo($safeBaseName, PATHINFO_EXTENSION); $counter = 1; while (true) { $candidatePath = $dir . $candidateName; $existing = $uploadedFilesService->findFile(['file_path' => $candidatePath]); if (!$existing) { break; } // 若存在同路径同名,且类型也相同,则追加序号 if (isset($existing->file_type) && strtolower($existing->file_type) === strtolower($mime)) { $suffix = ' (' . $counter . ')'; $candidateName = $nameBody . $suffix . ($nameExt !== '' ? ('.' . $nameExt) : ''); $counter++; continue; } // 类型不同则允许同名,结束循环 break; } $objectKey = $dir . $candidateName; $ossService = new OssService(); $ossService->uploadImage($filePath, $objectKey); $privateUrl = $ossService->generatePrivateUrl($objectKey); // 记录文件信息到数据库 $uploadedFilesService = new UploadedFilesService(); $fileInfo = [ 'file_name' => basename($objectKey), 'file_path' => $objectKey, 'file_size' => $size, 'file_type' => $mime, 'original_name' => $originalName, ]; $recordResult = $uploadedFilesService->recordFileInfo($fileInfo, null, $scene, $category); $data = [ 'original_name' => $originalName, 'file_name' => $objectKey, 'file_url' => $privateUrl, 'file_id' => $recordResult['id'] ?? null, 'partition' => $scene, 'category' => $category, ]; return $data; } catch (\Throwable $e) { Log::error($e->getMessage(),$param); throw new BusinessException($e->getMessage()); } } /** * 获取文件的 MIME 类型 * 优先使用 mime_content_type(),不可用时根据扩展名判断 * * @param string $filePath 文件路径 * @param string $extension 文件扩展名 * @return string */ private function getMimeType(string $filePath, string $extension = ''): string { // 优先使用系统函数 if (function_exists('mime_content_type')) { $mime = mime_content_type($filePath); if ($mime !== false && $mime !== '') { return $mime; } } // 降级:根据扩展名判断 $extension = strtolower(ltrim($extension, '.')); $mimeTypes = [ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', 'bmp' => 'image/bmp', 'svg' => 'image/svg+xml', 'pdf' => 'application/pdf', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'xls' => 'application/vnd.ms-excel', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'mp4' => 'video/mp4', 'mp3' => 'audio/mpeg', 'txt' => 'text/plain', ]; return $mimeTypes[$extension] ?? 'application/octet-stream'; } /** * 删除 OSS 上的文件 * * @param array $param * - object_key: OSS 对象键名-oss路径(必需) * - file_id: 数据库文件记录ID(可选,用于删除数据库记录) * @return bool 删除是否成功 * * 示例 * $uploadService = new UploadService(); * * 只删除 OSS 文件 * $uploadService->deleteOssFile([ * 'object_key' => 'vehicle_album/documents/20241201/abc123.pdf' * ]); * * 同时删除 OSS 文件和数据库记录 * $uploadService->deleteOssFile([ * 'object_key' => 'vehicle_album/images/20241201/abc123.jpg', * 'file_id' => 123 * ]); */ public function deleteOssFile($objectKey,$fileId = null) { try { if (empty($objectKey)) { Log::error('OSS对象键名不能为空', $objectKey); throw new BusinessException('OSS对象键名不能为空'); } $uploadedFilesService = new UploadedFilesService(); // 如果提供了文件ID,同时删除数据库记录 if ($fileId) { $uploadedFilesService->deleteFile($fileId); }else{ $uploadedFilesService = new UploadedFilesService(); if (empty($fileId)) { $where = ['file_path' => $objectKey]; $file = $uploadedFilesService->getFile($where); $fileId = $file->id; } if(!empty($fileId)){ $uploadedFilesService->deleteFile($fileId); } } // 删除 OSS 上的文件 $ossService = new OssService(); $ossService->deleteFile($objectKey); Log::info('OSS文件删除成功', ['object_key' => $objectKey, 'file_id' => $fileId]); return true; } catch (\Throwable $e) { Log::error('删除OSS文件失败: ' . $e->getMessage()); throw new BusinessException('删除OSS文件失败: ' . $e->getMessage()); } } }