diff --git a/app/Http/Controllers/Api/V1/FileStorageController.php b/app/Http/Controllers/Api/V1/FileStorageController.php index 95e4e4d0..41e6486c 100644 --- a/app/Http/Controllers/Api/V1/FileStorageController.php +++ b/app/Http/Controllers/Api/V1/FileStorageController.php @@ -9,6 +9,7 @@ use App\Http\Requests\Api\V1\ShareLinkRequest; use App\Services\FileStorageService; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; class FileStorageController extends Controller { @@ -122,6 +123,28 @@ public function view(int $id, Request $request) return $file->download(inline: true); } + /** + * R2 Presigned URL 발급 (30분 유효) + */ + public function presignedUrl(int $id, Request $request) + { + $this->ensureContext($request); + + $service = new FileStorageService; + $file = $service->getFile($id); + + if (! $file->file_path || ! Storage::disk('r2')->exists($file->file_path)) { + abort(404, 'File not found in storage'); + } + + $url = Storage::disk('r2')->temporaryUrl( + $file->file_path, + now()->addMinutes(30) + ); + + return ApiResponse::handle(fn () => ['url' => $url]); + } + /** * Soft delete file */ diff --git a/routes/api/v1/files.php b/routes/api/v1/files.php index 4f48bc91..bed1b821 100644 --- a/routes/api/v1/files.php +++ b/routes/api/v1/files.php @@ -22,6 +22,7 @@ Route::get('/{id}', [FileStorageController::class, 'show'])->name('v1.files.show'); // 파일 상세 Route::get('/{id}/download', [FileStorageController::class, 'download'])->name('v1.files.download'); // 파일 다운로드 Route::get('/{id}/view', [FileStorageController::class, 'view'])->name('v1.files.view'); // 파일 인라인 보기 (이미지/PDF) + Route::get('/{id}/presigned-url', [FileStorageController::class, 'presignedUrl'])->name('v1.files.presigned-url'); // R2 Presigned URL 발급 Route::delete('/{id}', [FileStorageController::class, 'destroy'])->name('v1.files.destroy'); // 파일 삭제 (soft) Route::post('/{id}/restore', [FileStorageController::class, 'restore'])->name('v1.files.restore'); // 파일 복구 Route::delete('/{id}/permanent', [FileStorageController::class, 'permanentDelete'])->name('v1.files.permanent'); // 파일 영구 삭제