diff --git a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php index b1f22c13..b625f122 100644 --- a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php +++ b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Controller; use App\Models\Boards\File; +use App\Services\GoogleCloudStorageService; use App\Services\HR\EmployeeService; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -256,9 +257,9 @@ public function destroy(Request $request, int $id): JsonResponse|Response } /** - * 사원 첨부파일 업로드 + * 사원 첨부파일 업로드 (로컬 + GCS 듀얼 저장) */ - public function uploadFile(Request $request, int $id): JsonResponse + public function uploadFile(Request $request, int $id, GoogleCloudStorageService $gcs): JsonResponse { $employee = $this->employeeService->getEmployeeById($id); if (! $employee) { @@ -275,8 +276,18 @@ public function uploadFile(Request $request, int $id): JsonResponse foreach ($request->file('files') as $file) { $storedName = Str::random(40).'.'.$file->getClientOriginalExtension(); - $path = "tenants/{$tenantId}/employees/{$employee->id}"; - $file->storeAs($path, $storedName, 'tenant'); + $storagePath = "employees/{$tenantId}/{$employee->id}/{$storedName}"; + + // 로컬 저장 + Storage::disk('tenant')->put($storagePath, file_get_contents($file)); + + // GCS 업로드 + $gcsUri = null; + $gcsObjectName = null; + if ($gcs->isAvailable()) { + $gcsObjectName = $storagePath; + $gcsUri = $gcs->upload($file->getRealPath(), $gcsObjectName); + } $fileRecord = File::create([ 'tenant_id' => $tenantId, @@ -284,10 +295,12 @@ public function uploadFile(Request $request, int $id): JsonResponse 'document_type' => 'employee_profile', 'original_name' => $file->getClientOriginalName(), 'stored_name' => $storedName, - 'file_path' => $path.'/'.$storedName, + 'file_path' => $storagePath, 'mime_type' => $file->getMimeType(), 'file_size' => $file->getSize(), 'file_type' => strtolower($file->getClientOriginalExtension()), + 'gcs_object_name' => $gcsObjectName, + 'gcs_uri' => $gcsUri, 'uploaded_by' => auth()->id(), 'created_by' => auth()->id(), ]); @@ -303,9 +316,9 @@ public function uploadFile(Request $request, int $id): JsonResponse } /** - * 사원 첨부파일 삭제 + * 사원 첨부파일 삭제 (GCS + 로컬 모두 삭제) */ - public function deleteFile(int $id, int $fileId): JsonResponse + public function deleteFile(int $id, int $fileId, GoogleCloudStorageService $gcs): JsonResponse { $tenantId = session('selected_tenant_id'); @@ -319,16 +332,27 @@ public function deleteFile(int $id, int $fileId): JsonResponse return response()->json(['success' => false, 'message' => '파일을 찾을 수 없습니다.'], 404); } - Storage::disk('tenant')->delete($file->file_path); + // GCS 삭제 + if ($gcs->isAvailable() && $file->gcs_object_name) { + $gcs->delete($file->gcs_object_name); + } + + // 로컬 삭제 + if ($file->file_path && Storage::disk('tenant')->exists($file->file_path)) { + Storage::disk('tenant')->delete($file->file_path); + } + + $file->deleted_by = auth()->id(); + $file->save(); $file->delete(); return response()->json(['success' => true, 'message' => '파일이 삭제되었습니다.']); } /** - * 사원 첨부파일 다운로드 + * 사원 첨부파일 다운로드 (GCS Signed URL 우선, 로컬 폴백) */ - public function downloadFile(int $id, int $fileId) + public function downloadFile(int $id, int $fileId, GoogleCloudStorageService $gcs) { $tenantId = session('selected_tenant_id'); @@ -342,12 +366,21 @@ public function downloadFile(int $id, int $fileId) abort(404, '파일을 찾을 수 없습니다.'); } - $disk = Storage::disk('tenant'); - if (! $disk->exists($file->file_path)) { - abort(404, '파일이 서버에 존재하지 않습니다.'); + // GCS Signed URL로 리다이렉트 + if ($gcs->isAvailable() && $file->gcs_object_name) { + $signedUrl = $gcs->getSignedUrl($file->gcs_object_name, 60); + if ($signedUrl) { + return redirect($signedUrl); + } } - return $disk->download($file->file_path, $file->original_name); + // 로컬 폴백 + $disk = Storage::disk('tenant'); + if ($file->file_path && $disk->exists($file->file_path)) { + return $disk->download($file->file_path, $file->original_name); + } + + abort(404, '파일이 서버에 존재하지 않습니다.'); } /**