normalizePath($path); if ($normalizedPath === '') { throw new AttachmentStorageException('The attachment path cannot be empty.'); } $filename = basename($normalizedPath); if ($filename === '' || $filename === '.' || $filename === DIRECTORY_SEPARATOR) { throw new AttachmentStorageException('The attachment filename cannot be empty.'); } $key = (string) Str::uuid(); $storedPath = Storage::disk('s3')->putFileAs( $this->directoryFromPath($normalizedPath), $file, $key, ); if (! is_string($storedPath) || $storedPath === '') { throw new AttachmentStorageException('No se pudo subir el archivo al disco s3.'); } try { /** @var Attachment $attachment */ $attachment = Attachment::query()->create([ 'key' => $key, 'path' => $storedPath, 'filename' => $filename, 'type' => $this->resolveAttachmentType($file), 'mime_type' => $file->getClientMimeType() ?? $file->getMimeType() ?? 'application/octet-stream', 'extension' => $file->extension(), 'size' => $file->getSize() ?? 0, ]); return $attachment; } catch (Throwable $throwable) { Storage::disk('s3')->delete($storedPath); throw $throwable; } } public function delete(Attachment $attachment): void { $deleted = Storage::disk('s3')->delete($attachment->path); if (! $deleted) { throw new AttachmentStorageException('No se pudo eliminar el archivo del disco s3.'); } $attachment->delete(); } protected function normalizePath(string $path): string { return trim($path, '/'); } protected function directoryFromPath(string $path): string { $directory = dirname($path); if ($directory === '.' || $directory === DIRECTORY_SEPARATOR) { return ''; } return trim($directory, '/'); } protected function resolveAttachmentType(UploadedFile $file): AttachmentType { $mimeType = strtolower($file->getClientMimeType() ?? $file->getMimeType() ?? ''); if (str_starts_with($mimeType, 'image/')) { return AttachmentType::Image; } if (str_starts_with($mimeType, 'video/')) { return AttachmentType::Video; } if ($mimeType === 'application/pdf') { return AttachmentType::Pdf; } if (str_starts_with($mimeType, 'audio/')) { return AttachmentType::Audio; } if ( str_starts_with($mimeType, 'text/') || str_contains($mimeType, 'document') || str_contains($mimeType, 'word') || str_contains($mimeType, 'excel') || str_contains($mimeType, 'spreadsheet') || str_contains($mimeType, 'presentation') || str_contains($mimeType, 'officedocument') ) { return AttachmentType::Document; } return AttachmentType::Other; } }