validate([ 'filename' => ['required', 'string', 'max:255'], 'mime_type' => ['required', 'string', 'max:100'], ]); $extension = pathinfo($validated['filename'], PATHINFO_EXTENSION) ?: 'bin'; $key = 'temp/'.Str::uuid().'.'.$extension; $defaultDisk = config('filesystems.default'); if ($defaultDisk === 's3') { $s3 = new S3Client([ 'region' => config('filesystems.disks.s3.region'), 'endpoint' => config('filesystems.disks.s3.endpoint'), 'use_path_style_endpoint' => config('filesystems.disks.s3.use_path_style_endpoint'), 'credentials' => [ 'key' => config('filesystems.disks.s3.key'), 'secret' => config('filesystems.disks.s3.secret'), ], ]); $command = $s3->getCommand('PutObject', [ 'Bucket' => config('filesystems.disks.s3.bucket'), 'Key' => $key, 'ContentType' => $validated['mime_type'], ]); $presignedUrl = (string) $s3->createPresignedRequest($command, '+15 minutes')->getUri(); } else { $presignedUrl = route('media.local-upload', ['key' => $key]); } return response()->json([ 'key' => $key, 'url' => $presignedUrl, 'expires_at' => now()->addMinutes(15)->toISOString(), ]); } public function localUpload(Request $request): JsonResponse { $key = $request->query('key'); if (! $key || ! str_starts_with($key, 'temp/')) { return response()->json(['error' => 'Invalid key'], 400); } $content = $request->getContent(); $disk = config('filesystems.default') === 's3' ? 's3' : config('filesystems.default', 'public'); Storage::disk($disk)->put($key, $content); return response()->json(['success' => true]); } }