Como desenvolver uma aplicação Node.js para upload direto de arquivos via web para um bucket S3

Passo 1: Configuração do Projeto
2. Crie uma nova pasta para o projeto:
mkdir node-s3-upload
cd node-s3-upload
2. Inicialize o projeto Node.js:
npm init -y
3. Instale as dependências necessárias:
npm install express cors multer @aws-sdk/client-s3 @aws-sdk/lib-storage dotenv
4. Instale o
nodemon
para desenvolvimento (opcional):
npm install — save-dev nodemon
5. Crie o arquivo
.env
:
Crie um arquivo .env
na raiz do projeto e adicione as credenciais da AWS:
AWS_ACCESS_KEY_ID=acesskey
AWS_SECRET_ACCESS_KEY=secretkey
AWS_REGION=region
S3_BUCKET_NAME=nomedobucket
PORT=3000
Passo 2: Configuração do Servidor
Crie o arquivo
server.js
:
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { Upload } = require('@aws-sdk/lib-storage');
const app = express();
const port = process.env.PORT || 3000;
// Configuração do AWS SDK v3
const s3Client = new S3Client({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});
// Configuração do Multer para armazenar arquivos localmente antes do upload
const storage = multer.memoryStorage();
const upload = multer({ storage });
// Função para realizar o upload no S3
async function uploadToS3(file) {
const key = `${Date.now()}-${file.originalname}`;
const upload = new Upload({
client: s3Client,
params: {
Bucket: process.env.S3_BUCKET_NAME,
Key: key, // Nome do arquivo no S3
Body: file.buffer, // Arquivo em buffer da memória
ContentType: file.mimetype, // Define o tipo MIME
},
});
await upload.done(); // Executa o upload
const fileUrl = `https://${process.env.S3_BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${key}`;
// Log detalhado para verificar o upload bem-sucedido
console.log(`Arquivo enviado com sucesso: ${file.originalname}`);
console.log(`URL do arquivo: ${fileUrl}`);
return fileUrl;
}
// Middleware para permitir CORS e JSON
app.use(cors());
app.use(express.json());
// Rota para upload de arquivos
app.post('/upload', upload.array('files', 10), async (req, res) => {
try {
const fileUrls = await Promise.all(
req.files.map(file => {
console.log(`Iniciando upload do arquivo: ${file.originalname}`);
return uploadToS3(file);
})
);
console.log('Todos os arquivos foram enviados com sucesso!');
res.status(200).json({ message: 'Upload realizado com sucesso!', fileUrls });
} catch (error) {
console.error('Erro ao fazer upload:', error);
res.status(500).json({ error: 'Erro ao fazer upload dos arquivos.' });
}
});
// Iniciar o servidor
app.use(express.static('public'));
app.listen(port, () => {
console.log(`Servidor rodando na porta ${port}`);
});
Passo 3: Criar a Interface de Arrastar e Soltar
- Crie uma pasta
public
na raiz do projeto:
mkdir public
2. Crie o arquivo index.html
dentro da pasta public
:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload de Arquivos para S3</title>
<style>
/* Estilos para o tema dark */
body {
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0;
padding: 20px;
background-color: #121212;
color: #fff;
}
h1 {
font-size: 2rem;
color: #fff;
margin-bottom: 30px;
}
/* Box de upload */
.upload-box {
border: 2px dashed #bbb;
padding: 20px;
text-align: center;
width: 300px;
background-color: #1f1f1f;
border-radius: 10px;
margin-bottom: 20px;
transition: all 0.3s ease;
}
.upload-box.dragover {
border-color: #00c9ff;
background-color: #333;
}
#file-input {
display: none;
}
.upload-button {
background-color: #007bff;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.upload-button:hover {
background-color: #0056b3;
}
/* Galeria de imagens */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 10px;
width: 100%;
max-width: 800px;
}
.gallery-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px solid #444;
border-radius: 5px;
padding: 10px;
background-color: #222;
}
.gallery-item img {
max-width: 100%;
max-height: 100px;
margin-bottom: 5px;
border-radius: 5px;
}
.gallery-item p {
word-wrap: break-word;
font-size: 14px;
text-align: center;
color: #bbb;
}
.file-link {
margin-top: 5px;
color: #00c9ff;
text-decoration: none;
font-size: 12px;
word-wrap: break-word;
}
/* Logo da AWS */
.aws-logo {
margin-top: 30px;
max-width: 200px;
}
</style>
</head>
<!-- Logo da AWS centralizada -->
<img src="https://logos-world.net/wp-content/uploads/2021/08/Amazon-Web-Services-AWS-Logo.png" alt="AWS Logo" class="aws-logo">
<body>
<h1>Upload de Arquivos para o S3</h1>
<div class="upload-box" id="upload-box">
<p>Arraste e solte arquivos aqui ou clique para selecionar</p>
<input type="file" id="file-input" multiple accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx">
<button class="upload-button" onclick="document.getElementById('file-input').click()">Selecionar Arquivos</button>
</div>
<div class="gallery" id="gallery"></div>
<script>
const uploadBox = document.getElementById('upload-box');
const fileInput = document.getElementById('file-input');
const gallery = document.getElementById('gallery');
uploadBox.addEventListener('dragover', (e) => {
e.preventDefault();
uploadBox.classList.add('dragover');
});
uploadBox.addEventListener('dragleave', () => {
uploadBox.classList.remove('dragover');
});
uploadBox.addEventListener('drop', (e) => {
e.preventDefault();
uploadBox.classList.remove('dragover');
const files = e.dataTransfer.files;
handleFiles(files);
});
fileInput.addEventListener('change', (e) => {
const files = e.target.files;
handleFiles(files);
});
async function handleFiles(files) {
const formData = new FormData();
gallery.innerHTML = ''; // Limpa a galeria antes de adicionar novos arquivos
for (const file of files) {
formData.append('files', file);
// Adiciona à galeria
const galleryItem = document.createElement('div');
galleryItem.classList.add('gallery-item');
if (file.type.startsWith('image/')) {
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
img.onload = () => URL.revokeObjectURL(img.src); // Libera memória
galleryItem.appendChild(img);
} else {
const placeholder = document.createElement('p');
placeholder.textContent = file.name;
galleryItem.appendChild(placeholder);
}
gallery.appendChild(galleryItem);
}
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData,
});
const result = await response.json();
// Exibe os links de acesso externo para os arquivos
result.fileUrls.forEach((url, index) => {
const galleryItem = gallery.children[index];
const link = document.createElement('a');
link.href = url;
link.textContent = 'Acessar Arquivo';
link.target = '_blank';
link.classList.add('file-link');
galleryItem.appendChild(link);
});
alert(result.message);
console.log('URLs dos arquivos:', result.fileUrls);
} catch (error) {
console.error('Erro ao fazer upload:', error);
alert('Erro ao fazer upload dos arquivos.');
}
}
</script>
</body>
</html>
Passo 4: Executar o Projeto
- Inicie o servidor:
node server.js
Alternativas: - npm start
- node server.js
- Acesse a aplicação:
Abra o navegador e acessehttp://localhost:3000
. Você verá a interface de arrastar e soltar. Faça o upload de arquivos e eles serão enviados diretamente para o bucket S3.
Conclusão do projeto:

O bucket continua 100% privado, você poderá fazer isso de forma publica.
Este projeto foi criado, containerizado e implantado de forma segura, com variáveis utilizando CI/CD com GitLab.
Caso deseje o fluxo completo, entre em contato conosco."