AWS S3 COPY - Copiar Arquivo entre Buckets/Pastas
O que é este Node?
O AWS S3 COPY é o node responsável por copiar arquivos entre buckets S3 ou entre pastas dentro do mesmo bucket sem precisar baixar e fazer upload novamente.
Por que este Node existe?
Copiar arquivos no S3 de forma eficiente é crucial. O S3 COPY existe para:
- Backup entre buckets: Copiar de produção para backup
- Organização: Mover arquivos entre pastas (copy + delete)
- Replicação manual: Duplicar arquivos para outras regiões
- Versionamento manual: Criar cópias com novos nomes
- Eficiência: Copiar server-side (sem download/upload)
Como funciona internamente?
Quando o S3 COPY é executado, o sistema:
- Recebe credenciais AWS: Access Key ID, Secret Access Key e região
- Localiza arquivo origem: sourceBucket + sourceKey
- Define destino: destinationBucket + destinationKey
- Copia server-side: S3 copia internamente (sem tráfego)
- Preserva metadados: ContentType, metadata original
- Retorna confirmação: CopyResult com metadados
Código interno (aws-executors.service.ts:71-80):
case 'copy':
const copyResult = await s3.copyObject({
Bucket: data.destinationBucket,
CopySource: `${data.sourceBucket}/${data.sourceKey}`,
Key: data.destinationKey,
}).promise();
return {
success: true,
copyResult,
};
Quando você DEVE usar este Node?
Use S3 COPY sempre que precisar duplicar arquivos no S3:
Casos de uso
- Backup manual: Copiar arquivo importante para bucket de backup
- Reorganização: Mover arquivo de temp/ para permanente/
- Duplicação para processamento: Criar cópia antes de modificar
- Migração entre regiões: Copiar de us-east-1 para sa-east-1
- Versionamento: Criar backup-YYYY-MM-DD.json
Quando NÃO usar S3 COPY
- Replicação automática: Use S3 Replication Rules
- Arquivos gigantes (>5GB): Use Multipart Copy
- Cross-account: Precisa permissões especiais
Parâmetros Detalhados
accessKeyId (string, obrigatório)
O que é: Sua AWS Access Key ID (credencial de autenticação).
Onde conseguir: IAM Console → Users → Security credentials → Create access key
Flow completo para testar:
{
"name": "Teste S3 Copy - Access Key",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Copiar S3",
"parameters": {
"operation": "copy",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"sourceBucket": "bucket-origem",
"sourceKey": "documentos/original.pdf",
"destinationBucket": "bucket-destino",
"destinationKey": "backup/copia.pdf"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Arquivo copiado com sucesso!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Substitua pelos seus dados reais. Arquivo será copiado server-side.
secretAccessKey (string, obrigatório)
O que é: Sua AWS Secret Access Key (senha da credencial).
Segurança: NUNCA exponha essa chave! Use variáveis de ambiente.
region (string, obrigatório)
O que é: Região AWS onde estão os buckets.
IMPORTANTE: Para copy cross-region, use região do bucket de DESTINO.
Valores comuns:
- us-east-1 (Norte da Virgínia)
- us-west-2 (Oregon)
- sa-east-1 (São Paulo)
- eu-west-1 (Irlanda)
Flow completo para testar:
{
"name": "Teste S3 Copy - Cross Region",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Copiar USA → Brasil",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "sa-east-1",
"sourceBucket": "bucket-usa",
"sourceKey": "data/arquivo.json",
"destinationBucket": "bucket-brasil",
"destinationKey": "data/arquivo.json"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "Arquivo replicado de USA para Brasil!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
sourceBucket (string, obrigatório)
O que é: Nome do bucket S3 onde está o arquivo original.
Flow completo para testar:
{
"name": "Teste S3 Copy - Source Bucket",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Backup",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"sourceBucket": "uploads-producao",
"sourceKey": "importante/arquivo.pdf",
"destinationBucket": "backups",
"destinationKey": "importante/arquivo-backup.pdf"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Backup criado em bucket 'backups'!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
sourceKey (string, obrigatório)
O que é: Caminho completo do arquivo original no bucket origem.
Formato: pasta/subpasta/arquivo.ext
Flow completo para testar:
{
"name": "Teste S3 Copy - Source Key Dinâmica",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Pedir Arquivo",
"parameters": {
"message": "Digite o nome do arquivo a copiar:",
"variable": "nome_arquivo"
}
}
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Copiar",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"sourceBucket": "uploads",
"sourceKey": "temp/{{nome_arquivo}}",
"destinationBucket": "uploads",
"destinationKey": "permanente/{{nome_arquivo}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "{{nome_arquivo}} movido de temp/ para permanente/"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
destinationBucket (string, obrigatório)
O que é: Nome do bucket S3 de destino (pode ser o mesmo que origem).
Flow completo para testar:
{
"name": "Teste S3 Copy - Mesmo Bucket",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Duplicar no Mesmo Bucket",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"sourceBucket": "meu-bucket",
"sourceKey": "original/arquivo.pdf",
"destinationBucket": "meu-bucket",
"destinationKey": "backup/arquivo-2025-01-15.pdf"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Cópia criada em backup/ com data!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
destinationKey (string, obrigatório)
O que é: Caminho completo do arquivo de destino.
IMPORTANTE: Se já existir, será sobrescrito!
Flow completo para testar:
{
"name": "Teste S3 Copy - Destination Key com Data",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Gerar Nome Backup",
"parameters": {
"variable": "backup_nome",
"value": "backup-2025-01-15-{{timestamp}}.json"
}
}
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Criar Backup Datado",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"sourceBucket": "dados",
"sourceKey": "atual/dados.json",
"destinationBucket": "dados",
"destinationKey": "backups/{{backup_nome}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "Backup criado: {{backup_nome}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "s3_1" },
{ "source": "s3_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | Deve ser "copy" |
| accessKeyId | string | Sim | AWS Access Key ID |
| secretAccessKey | string | Sim | AWS Secret Access Key |
| region | string | Sim | Região AWS (do bucket destino) |
| sourceBucket | string | Sim | Bucket origem |
| sourceKey | string | Sim | Caminho do arquivo origem |
| destinationBucket | string | Sim | Bucket destino |
| destinationKey | string | Sim | Caminho do arquivo destino |
Exemplo 1: Backup Diário Automatizado
Objetivo: Criar backup diário de arquivo crítico com data no nome.
JSON para Importar
{
"name": "Backup Diário Automatizado",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Data Atual",
"parameters": {
"variable": "data_hoje",
"value": "2025-01-15"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Iniciando",
"parameters": {
"message": "Iniciando backup diário de {{data_hoje}}..."
}
}
},
{
"id": "s3_1",
"type": "aws_s3",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Copiar Banco de Dados",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "sa-east-1",
"sourceBucket": "producao-dados",
"sourceKey": "database/production.db",
"destinationBucket": "backups-diarios",
"destinationKey": "database/backup-{{data_hoje}}.db"
}
}
},
{
"id": "s3_2",
"type": "aws_s3",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Copiar Configurações",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "sa-east-1",
"sourceBucket": "producao-dados",
"sourceKey": "config/app.config.json",
"destinationBucket": "backups-diarios",
"destinationKey": "config/config-{{data_hoje}}.json"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Concluído",
"parameters": {
"message": "Backup de {{data_hoje}} CONCLUÍDO!\n\n- Database: backup-{{data_hoje}}.db\n- Config: config-{{data_hoje}}.json"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "message_1" },
{ "source": "message_1", "target": "s3_1" },
{ "source": "s3_1", "target": "s3_2" },
{ "source": "s3_2", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: Iniciando backup diário de 2025-01-15...
Sistema: Backup de 2025-01-15 CONCLUÍDO!
- Database: backup-2025-01-15.db
- Config: config-2025-01-15.json
Exemplo 2: Mover Arquivo (Copy + Delete)
Objetivo: Mover arquivo de pasta temporária para permanente.
JSON para Importar
{
"name": "Mover Arquivo - Temp para Permanente",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "ID Documento",
"parameters": {
"message": "Digite o ID do documento processado:",
"variable": "doc_id"
}
}
},
{
"id": "s3_copy_1",
"type": "aws_s3",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Copiar para Permanente",
"parameters": {
"operation": "copy",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"sourceBucket": "uploads",
"sourceKey": "temp/doc-{{doc_id}}.pdf",
"destinationBucket": "uploads",
"destinationKey": "permanente/doc-{{doc_id}}.pdf"
}
}
},
{
"id": "s3_delete_1",
"type": "aws_s3",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Deletar Temporário",
"parameters": {
"operation": "delete",
"accessKeyId": "SUA_ACCESS_KEY",
"secretAccessKey": "SUA_SECRET_KEY",
"region": "us-east-1",
"bucketName": "uploads",
"key": "temp/doc-{{doc_id}}.pdf"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Concluído",
"parameters": {
"message": "Documento {{doc_id}} MOVIDO com sucesso!\n\nDe: temp/\nPara: permanente/"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "s3_copy_1" },
{ "source": "s3_copy_1", "target": "s3_delete_1" },
{ "source": "s3_delete_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite o ID do documento processado:
Usuário: 123
Sistema: Documento 123 MOVIDO com sucesso!
De: temp/
Para: permanente/
Resposta do Node
{
"success": true,
"copyResult": {
"CopyObjectResult": {
"ETag": "\"abc123def456\"",
"LastModified": "2025-01-15T10:30:00.000Z"
}
}
}
Configuração AWS
Permissões IAM Necessárias
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::bucket-origem/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::bucket-destino/*"
}
]
}
IMPORTANTE: Precisa GetObject no origem E PutObject no destino!
Boas Práticas
Performance
SIM: - Copy é server-side (muito mais rápido que download+upload) - Para arquivos >5GB, use Multipart Copy - Copy entre mesma região é instantâneo - Copy cross-region tem custo de transferência
NÃO: - Não use copy para arquivos >5GB sem multipart - Não faça copy em loop (use batch operations)
Segurança
SIM: - Verifique permissões em AMBOS os buckets - Para cross-account, configure bucket policy - Preserve ACL se necessário (use CopySource + ACL) - Valide que arquivo origem existe antes
NÃO: - Não sobrescreva arquivos importantes sem backup - Não copie entre accounts sem policy correta
Organização
SIM: - Use copy para reorganizar estrutura de pastas - Crie backups com data no nome - Implemente "move" com copy + delete atômico
Padrão de backup com data:
original/arquivo.pdf
backup/arquivo-2025-01-15.pdf
backup/arquivo-2025-01-16.pdf
Custos
SIM: - Copy na mesma região é grátis (só armazenamento) - Copy cross-region tem custo de transferência - Consider lifecycle policies para deletar backups antigos
NÃO: - Não mantenha infinitos backups (configure lifecycle) - Não copie cross-region sem necessidade
Dicas
Server-side: Copy é 100% server-side. Nenhum dado passa pelo seu servidor.
Preservar metadata: Por padrão, metadata é copiado. Use MetadataDirective para controlar.
Sobrescrever: Se destinationKey já existe, será sobrescrito SEM aviso!
Move: S3 não tem "move" nativo. Faça copy + delete.
Cross-region: Funciona, mas tem custo de transferência entre regiões.
Same key: Pode copiar para mesma key (sobrescreve). Útil para atualizar metadata.
Versionamento: Se destino tem versionamento, cria nova versão.
ETag: Use ETag retornado para verificar integridade.
Próximo Node
→ S3 UPLOAD - Enviar arquivo para S3 → S3 DOWNLOAD - Baixar arquivo do S3 → S3 DELETE - Deletar arquivo do S3 → S3 LIST - Listar objetos no bucket