Exportar archivos a Amazon S3 en Node.js: una guía completa
Exportar archivos a Amazon S3 es un requisito habitual en las aplicaciones web modernas. Ya sea que estés creando un sistema de almacenamiento de archivos, implementando copias de seguridad o gestionando las subidas de los usuarios, es esencial entender cómo exportar archivos a Amazon S3 con Node.js de forma eficiente.
Requisitos previos
Antes de empezar, asegúrate de contar con:
- Node.js 20 o posterior instalado
- Una cuenta de AWS con credenciales de acceso
- Conocimientos básicos de JavaScript y Node.js
- Un proyecto configurado con "type": "module" en tu
package.json
Configurar las credenciales de AWS
Para interactuar con Amazon S3 desde tu aplicación de Node.js, necesitas configurar tus credenciales de AWS. Hay varias maneras de hacerlo:
-
Variables de entorno: define las siguientes variables de entorno en tu sistema o en tu archivo
.env:AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=YOUR_SECRET_ACCESS_KEY AWS_REGION=YOUR_AWS_REGION -
Archivo de credenciales compartidas: usa el archivo de credenciales de AWS ubicado en
~/.aws/credentials:[default] aws_access_key_id = YOUR_ACCESS_KEY_ID aws_secret_access_key = YOUR_SECRET_ACCESS_KEY -
Roles de IAM: si ejecutas tu aplicación en servicios de AWS como EC2, puedes asignar un rol de IAM a tu instancia y el AWS SDK usará esas credenciales automáticamente.
Instalar y usar el AWS SDK
Empezaremos con el AWS SDK oficial para JavaScript (v3). Instala los paquetes necesarios con:
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage
Este es un ejemplo básico para subir un archivo a Amazon S3:
import {
S3Client,
PutObjectCommand,
S3ServiceException,
type PutObjectCommandInput,
} from '@aws-sdk/client-s3'
import { createReadStream } from 'fs'
const s3Client = new S3Client({
region: 'us-east-1',
})
async function uploadFile(filePath: string, bucketName: string, key: string) {
try {
const uploadParams: PutObjectCommandInput = {
Bucket: bucketName,
Key: key,
Body: createReadStream(filePath),
}
const command = new PutObjectCommand(uploadParams)
await s3Client.send(command)
console.log('Upload completed successfully')
} catch (err) {
if (err instanceof S3ServiceException) {
console.error(`S3 Error: ${err.name} - ${err.message}`)
} else {
console.error('Upload failed:', err)
}
throw err
}
}
// Usage
await uploadFile('path/to/file.txt', 'my-bucket', 'file.txt')
Este ejemplo usa el PutObjectCommand para subir un archivo a S3. La función createReadStream
transmite el archivo mediante streaming para subirlo de forma eficiente.
Manejar archivos grandes con subida multiparte
Para archivos grandes, se recomienda usar subidas multiparte para mejorar la fiabilidad y el
rendimiento. El AWS SDK ofrece utilidades para simplificar este proceso. Usar la clase Upload de
@aws-sdk/lib-storage gestiona las subidas multiparte automáticamente:
import { S3Client, S3ServiceException } from '@aws-sdk/client-s3'
import { Upload } from '@aws-sdk/lib-storage'
import { createReadStream } from 'fs'
const s3Client = new S3Client({ region: 'us-east-1' })
async function uploadLargeFile(filePath: string, bucketName: string, key: string) {
try {
const upload = new Upload({
client: s3Client,
params: {
Bucket: bucketName,
Key: key,
Body: createReadStream(filePath),
},
})
upload.on('httpUploadProgress', (progress) => {
console.log(`Progress: ${progress.loaded}/${progress.total}`)
})
await upload.done()
console.log('Large file upload completed successfully')
} catch (err) {
if (err instanceof S3ServiceException) {
console.error(`S3 Error: ${err.name} - ${err.message}`)
} else {
console.error('Upload failed:', err)
}
}
}
// Usage
await uploadLargeFile('path/to/large-file.zip', 'my-bucket', 'large-file.zip')
Buenas prácticas de seguridad
Al exportar archivos a Amazon S3, es fundamental seguir las buenas prácticas de seguridad:
-
Usa roles de IAM: en lugar de codificar las claves de acceso en el código, usa roles de IAM cuando despliegues en servicios de AWS como EC2 o ECS. El AWS SDK usa HTTPS automáticamente y carga las credenciales desde variables de entorno, archivos de credenciales compartidas o roles de IAM, si están disponibles.
import { S3Client } from '@aws-sdk/client-s3' const s3Client = new S3Client({ region: 'us-east-1', maxAttempts: 3, }) -
Implementa el acceso con privilegios mínimos: restringe los permisos de tu usuario o rol de IAM solo a los necesarios para la tarea.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject"], "Resource": "arn:aws:s3:::your-bucket/*" } ] } -
Habilita el cifrado del lado del servidor: protege tus datos en reposo habilitando el cifrado del lado del servidor.
const uploadParams: PutObjectCommandInput = { Bucket: bucketName, Key: key, Body: createReadStream(filePath), ServerSideEncryption: 'AES256', } -
Usa HTTPS: el AWS SDK v3 usa HTTPS de forma predeterminada en todas las llamadas a la API, lo que garantiza que los datos en tránsito estén cifrados.
Manejo de errores y reintentos
La opción maxAttempts del SDK incluye la solicitud inicial y los reintentos con espera progresiva.
Sin embargo, un cuerpo de tipo stream que ya se consumió no se puede volver a enviar sin más.
Prefiere el helper Upload para archivos grandes y vuelve a abrir el stream del archivo si tu
aplicación reintenta por completo una subida fallida. Evita apilar un bucle de reintentos manual y
agresivo sobre la propia política de reintentos del SDK.
Compatibilidad con TypeScript
El AWS SDK para JavaScript v3 ofrece una sólida compatibilidad con TypeScript que ayuda a detectar errores durante el desarrollo y mejora el autocompletado en tu IDE. A continuación se muestra un ejemplo básico de cómo definir tipos al subir un archivo:
import { S3Client, PutObjectCommand, type PutObjectCommandInput } from '@aws-sdk/client-s3'
import { createReadStream } from 'fs'
const s3Client = new S3Client({ region: 'us-east-1' })
const uploadParams: PutObjectCommandInput = {
Bucket: 'my-bucket',
Key: 'my-key',
Body: createReadStream('file.txt'),
}
async function uploadFile() {
try {
const command = new PutObjectCommand(uploadParams)
await s3Client.send(command)
console.log('File uploaded successfully.')
} catch (error) {
console.error('Error uploading file:', error)
}
}
uploadFile()
Este ejemplo muestra cómo aprovechar TypeScript para definir y hacer cumplir la estructura de tus parámetros, lo que mejora el mantenimiento y permite detectar posibles problemas durante el desarrollo.
Conclusión
Exportar archivos a Amazon S3 con Node.js de forma eficiente implica entender cómo interactuar con el AWS SDK y seguir las buenas prácticas de seguridad y manejo de errores. Al aprovechar el AWS SDK e implementar las estrategias que vimos, puedes crear una funcionalidad robusta de exportación de archivos en tus aplicaciones de Node.js.
En Transloadit nos enfocamos en facilitar el procesamiento de archivos y las tareas de infraestructura. Si buscas una solución para gestionar la subida y el procesamiento de archivos sin complicaciones, conoce nuestros servicios con toda confianza.
