Trabajo con S3 y almacenamiento en la nube en TypeScript: bibliotecas, configuración y ejemplos de código
\n\nLos almacenes de objetos en la nube compatibles con la API de Amazon S3 se han convertido en el estándar de facto para almacenar y entregar archivos en aplicaciones web modernas. En el ecosistema de TypeScript y Node.js, existen varias herramientas potentes para trabajar con S3. En este artículo, analizaremos las principales bibliotecas, su configuración y proporcionaremos ejemplos prácticos de código para tareas típicas: carga, descarga, eliminación de archivos y gestión de buckets.
\n\nBibliotecas principales para trabajar con S3 en TypeScript
\n\nLa solución más popular y oficial es AWS SDK for JavaScript v3. Esta biblioteca está completamente reescrita en TypeScript, es modular y compatible con tree-shaking. Una alternativa es MinIO JavaScript Client, una biblioteca ligera totalmente compatible con la API de S3, ideal para trabajar con almacenes locales o autogestionados compatibles con S3 (por ejemplo, MinIO, Ceph, DigitalOcean Spaces).
\n\nPara escenarios simples, también se puede usar @aws-sdk/client-s3, un paquete independiente de AWS SDK v3 que contiene solo la funcionalidad necesaria para S3.
\n\nInstalación e inicialización
\n\nInstalemos el paquete principal para trabajar con S3 a través de AWS SDK v3:
\n\nnpm install @aws-sdk/client-s3 @aws-sdk/credential-providers\n\nPara trabajar con MinIO:
\n\nnpm install minio\n\nEjemplo de inicialización de un cliente S3 usando AWS SDK v3:
\n\nimport { S3Client } from "@aws-sdk/client-s3";\nimport { fromEnv } from "@aws-sdk/credential-providers";\n\nconst s3Client = new S3Client({\n region: "us-east-1",\n credentials: fromEnv(), // usa AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY de las variables de entorno\n});\n\nPara MinIO, el cliente se configura de la siguiente manera:
\n\nimport * as Minio from "minio";\n\nconst minioClient = new Minio.Client({\n endPoint: "play.min.io",\n port: 9000,\n useSSL: true,\n accessKey: "YOUR_ACCESS_KEY",\n secretKey: "YOUR_SECRET_KEY",\n});\n\nTipificación y tipos estrictos
\n\nUna de las principales ventajas de TypeScript es la tipificación estricta. Ambas bibliotecas proporcionan tipos completos para todas las solicitudes y respuestas. Por ejemplo, al cargar un archivo en S3, obtienes autocompletado para todos los parámetros:
\n\nimport { PutObjectCommand } from "@aws-sdk/client-s3";\n\nconst uploadParams: PutObjectCommand["input"] = {\n Bucket: "my-bucket",\n Key: "uploads/photo.jpg",\n Body: fileBuffer,\n ContentType: "image/jpeg",\n ACL: "public-read",\n};\n\nconst command = new PutObjectCommand(uploadParams);\nconst result = await s3Client.send(command);\n\nOperaciones principales: carga, descarga, eliminación
\n\n1. Carga de archivo (Upload)
\n\nimport { PutObjectCommand } from "@aws-sdk/client-s3";\n\nasync function uploadFile(bucket: string, key: string, body: Buffer | Uint8Array | string) {\n const command = new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n });\n return await s3Client.send(command);\n}\n\n// Ejemplo de uso\nconst buffer = Buffer.from("¡Hola, S3!");\nawait uploadFile("my-bucket", "hello.txt", buffer);\n\n2. Descarga de archivo (Download)
\n\nimport { GetObjectCommand } from "@aws-sdk/client-s3";\n\nasync function downloadFile(bucket: string, key: string): Promise<Buffer> {\n const command = new GetObjectCommand({ Bucket: bucket, Key: key });\n const response = await s3Client.send(command);\n return Buffer.from(await response.Body!.transformToByteArray());\n}\n\n// Ejemplo\nconst fileContent = await downloadFile("my-bucket", "hello.txt");\nconsole.log(fileContent.toString());\n\n3. Eliminación de archivo
\n\nimport { DeleteObjectCommand } from "@aws-sdk/client-s3";\n\nasync function deleteFile(