Trabalhando com S3 e armazenamentos em nuvem em TypeScript: bibliotecas, configuração e exemplos de código
\n\nOs armazenamentos de objetos em nuvem compatíveis com a API Amazon S3 tornaram-se o padrão de facto para armazenar e entregar arquivos em aplicações web modernas. No ecossistema TypeScript e Node.js, existem várias ferramentas poderosas para trabalhar com S3. Neste artigo, abordaremos as principais bibliotecas, sua configuração e forneceremos exemplos práticos de código para tarefas típicas: upload, download, exclusão de arquivos e gerenciamento de buckets.
\n\nPrincipais bibliotecas para trabalhar com S3 em TypeScript
\n\nA solução mais popular e oficial é o AWS SDK for JavaScript v3. Esta biblioteca foi completamente reescrita em TypeScript, é modular e suporta tree-shaking. Uma alternativa é o MinIO JavaScript Client — uma biblioteca leve, totalmente compatível com a API S3, que é excelente para trabalhar com armazenamentos locais ou self-hosted compatíveis com S3 (por exemplo, MinIO, Ceph, DigitalOcean Spaces).
\n\nPara cenários simples, você também pode usar o @aws-sdk/client-s3 — um pacote separado do AWS SDK v3 que contém apenas a funcionalidade necessária para S3.
\n\nInstalação e inicialização
\n\nVamos instalar o pacote principal para trabalhar com S3 via AWS SDK v3:
\n\nnpm install @aws-sdk/client-s3 @aws-sdk/credential-providers\n\nPara trabalhar com MinIO:
\n\nnpm install minio\n\nExemplo de inicialização de um 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 e AWS_SECRET_ACCESS_KEY das variáveis de ambiente\n});\n\nPara o cliente MinIO, a configuração é feita da seguinte forma:
\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\nTipagem e tipos estritos
\n\nUma das principais vantagens do TypeScript é a tipagem estrita. Ambas as bibliotecas fornecem tipos completos para todas as requisições e respostas. Por exemplo, ao fazer upload de um arquivo para o S3, você obtém autocompletar para todos os 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\nOperações principais: upload, download, exclusão
\n\n1. Upload de arquivo
\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// Exemplo de uso\nconst buffer = Buffer.from("Olá, S3!");\nawait uploadFile("my-bucket", "hello.txt", buffer);\n\n2. Download de arquivo
\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// Exemplo\nconst fileContent = await downloadFile("my-bucket", "hello.txt");\nconsole.log(fileContent.toString());\n\n3. Exclusão de arquivo
\n\nimport { DeleteObjectCommand } from "@aws-sdk/client-s3";\n\nasync function deleteFile(