Crie Your Own Transferência de arquivos Service: Dev Tutorial
Construa a arquivo transfer service from scratch. Backend API design, storage integration, e user interface development tutorial.
Para construir o seu próprio serviço de transferência de ficheiros, precisa de cinco componentes: um frontend que fatia e opcionalmente encripta ficheiros no browser, uma API REST que cria sessões de upload e pré-assina URLs de armazenamento, armazenamento de objetos compatível com S3 (Cloudflare R2, Backblaze B2, ou MinIO), uma pequena base de dados de metadados (SQLite ou Postgres), e um reverse proxy com TLS 1.3. Com Node 22, Fastify e Vite, pode lançar um serviço ao estilo WeTransfer em cerca de 600 linhas de código e hospedar tudo por 5 a 15 euros por mês com tráfego moderado.
Escolher Primeiro a Camada de Armazenamento
A economia do armazenamento pode fazer ou desfazer um serviço de transferência de ficheiros. O AWS S3 cobra $0,09 por GB de egresso, o que significa que um download popular de 2 GB partilhado 1.000 vezes custa $180 só em largura de banda. O Cloudflare R2 cobra zero de egresso e $0,015 por GB armazenado. O Backblaze B2 cobra $0,01 por GB de egresso e $0,006 por GB armazenado. Para um serviço de transferência gratuito, o R2 é a escolha óbvia. O MinIO permite auto-hospedar semântica S3 no seu próprio hardware, o que funciona se já tiver largura de banda e discos disponíveis.
Use URLs pré-assinadas para que os clientes façam upload e download diretamente do armazenamento, nunca através do seu servidor. Isto mantém a sua API limitada pela CPU em vez de pela largura de banda.
Esboço da Superfície da API
Mantenha a API pequena. Cinco endpoints cobrem 95% do que precisa:
POST /sessions— criar uma sessão de upload, devolver ID e URLs multipart pré-assinadasPOST /sessions/:id/complete— finalizar um upload multipart, devolver URL de partilhaGET /shares/:id— devolver metadados do ficheiro (tamanho, expiração, downloads restantes)GET /shares/:id/download— devolver uma URL de download pré-assinadaDELETE /shares/:id— permitir que o proprietário revogue antecipadamente (requer um token de revogação)
Limite de taxa POST /sessions de forma agressiva — 20 por IP por hora é suficiente. Todos os endpoints devolvem JSON, usam Cache-Control: no-store, e definem Content-Security-Policy nas páginas HTML.
Ligação do Backend com Fastify
O Fastify fornece validação de esquema JSON, logging sensato e 30k req/s por core sem esforço. Um POST /sessions mínimo:
fastify.post('/sessions', {
schema: {
body: {
type: 'object', required: ['size'],
properties: {
size: { type: 'integer', minimum: 1, maximum: 10737418240 },
contentType: { type: 'string', maxLength: 120 }
}
}
}
}, async (req) => {
const id = nanoid(16);
const key = `blobs/${id}`;
const upload = await s3.createMultipartUpload({
Bucket: 'transfers', Key: key, ContentType: req.body.contentType
});
const partCount = Math.ceil(req.body.size / (8 * 1024 * 1024));
const urls = await Promise.all(
Array.from({ length: partCount }, (_, i) =>
getSignedUrl(s3, new UploadPartCommand({
Bucket: 'transfers', Key: key, UploadId: upload.UploadId, PartNumber: i + 1
}), { expiresIn: 3600 }))
);
db.prepare('INSERT INTO sessions VALUES (?, ?, ?, ?)')
.run(id, upload.UploadId, key, Date.now());
return { id, uploadId: upload.UploadId, partUrls: urls };
});
Teto de 10 GB, partes de 8 MB, validade de URL de 1 hora. Ajuste para o seu mix de tráfego.
Construção da Interface de Upload
Vite mais React mais zero biblioteca de UI chega a um drag-and-drop funcional em cerca de 150 linhas. A peça crítica é o worker de upload: lance um Web Worker dedicado, passe-lhe o handle do File e os URLs de parte, e peça-lhe para fazer PUT de cada chunk com concorrência de 3 vias. A thread principal mantém-se responsiva, as atualizações de progresso chegam via postMessage.
// worker.js
self.onmessage = async ({ data: { file, partUrls } }) => {
const partSize = 8 * 1024 * 1024;
const etags = [];
for (let i = 0; i < partUrls.length; i++) {
const blob = file.slice(i * partSize, (i + 1) * partSize);
const res = await fetch(partUrls[i], { method: 'PUT', body: blob });
etags[i] = res.headers.get('etag');
self.postMessage({ type: 'progress', done: i + 1, total: partUrls.length });
}
self.postMessage({ type: 'done', etags });
};
Adicione um campo de senha que derive uma chave via PBKDF2 (600.000 iterações, SHA-256) e passe cada chunk por AES-256-GCM antes do PUT. Isto transforma o seu serviço num serviço com encriptação ponta-a-ponta em vez de encriptação do lado do servidor.
Design do Esquema da Base de Dados
O SQLite via better-sqlite3 trata dezenas de milhões de linhas sem dificuldade. Mantenha o esquema enxuto:
CREATE TABLE sessions (
id TEXT PRIMARY KEY, upload_id TEXT, object_key TEXT, created_at INTEGER
);
CREATE TABLE shares (
id TEXT PRIMARY KEY, object_key TEXT, size_bytes INTEGER,
content_type TEXT, expires_at INTEGER, max_downloads INTEGER,
download_count INTEGER DEFAULT 0, revocation_token TEXT
);
CREATE INDEX idx_shares_expires ON shares(expires_at);
Sem tabela de utilizadores, sem email, sem logs de IP. Esta é uma escolha deliberada — torna a conformidade com o RGPD quase trivial. Um cron noturno elimina as linhas expiradas e os seus objetos S3:
const expired = db.prepare('SELECT object_key FROM shares WHERE expires_at < ?').all(Date.now());
for (const { object_key } of expired) {
await s3.deleteObject({ Bucket: 'transfers', Key: object_key });
}
db.prepare('DELETE FROM shares WHERE expires_at < ?').run(Date.now());
Implementação de Links de Partilha e Downloads
Os URLs de partilha têm o aspeto https://suaapp.com/f/abc123#k=<base64key> quando adicionou encriptação do lado do cliente. O fragmento mantém a chave fora dos logs do servidor. A página de download busca /shares/abc123, obtém uma URL S3 pré-assinada, transmite bytes diretamente do R2, desencripta no browser, e entrega o resultado ao StreamSaver.js ou à File System Access API.
Defina Content-Disposition: attachment; filename*=UTF-8''nome-codificado para que o browser acione um diálogo de gravação em vez de renderizar o ficheiro inline. Isto importa para PDFs, ficheiros HTML e SVG, todos os quais podem executar scripts num contexto de browser de outra forma.
Proteção Contra Abusos
Os serviços de transferência de ficheiros atraem abusos. Espere três categorias: distribuição de malware, hospedagem de payloads de phishing e uploads com violação de direitos de autor. Mitigações por ordem de impacto: limite de taxa de uploads por IP, exija um tamanho mínimo (abaixo de 10 KB é quase sempre lixo), calcule um SHA-256 do ciphertext e verifique contra uma lista de hashes conhecidos como maus, e forneça um formulário de denúncia de abuso sem fricção. O ClamAV em conteúdo desencriptado só funciona quando tem a chave, o que derrota a encriptação ponta-a-ponta — a resposta correta são limites de taxa agnósticos ao conteúdo mais remoções responsivas.
Assine cada URL pré-assinada com um TTL curto (máximo 1 hora) e ligue as sessões a um token efémero gerado pelo browser armazenado num cookie Secure; HttpOnly; SameSite=Strict.
Deployment e Operação a Baixo Custo
Um único Hetzner CX22 de $10 (2 vCPU, 4 GB RAM) corre Fastify + SQLite + um reverse proxy Caddy e trata de milhares de utilizadores ativos. O Caddy dá-lhe TLS 1.3 automaticamente via Let's Encrypt. Coloque a Cloudflare à frente para proteção DDoS e o WAF gratuito. Monitorize com Uptime Kuma (gratuito, auto-hospedado) e registe em stdout capturado pelo journald.
Para redundância geográfica, replique o SQLite com Litestream para R2, e aponte uma segunda região para o mesmo armazenamento de objetos. O failover é ao nível do DNS. Toda a sua história de recuperação de desastres cabe num guardanapo.
O que Deixar de Fora até Precisar
Não construa contas, equipas ou pastas na v1. Não adicione entrega de email. Não implemente pré-visualização de vídeo ou miniaturas de imagens (ambas forçam o servidor a ver o plaintext). Não lance uma aplicação móvel antes de a versão web ser sólida no Safari móvel. O HexaTransfer é construído essencialmente nesta abordagem — API Fastify, armazenamento R2, Web Crypto no browser, metadados SQLite, sem contas. A proliferação de funcionalidades que destruiu os clones antigos de transferência de ficheiros foi sempre o mesmo padrão: contas, depois quotas de armazenamento, depois pagamento, depois planos de equipa, e de repente estão a competir com a Dropbox em vez de lançar uma ferramenta de transferência rápida e privada.
Experimente em https://hexatransfer.com — gratuito, sem conta, máximo de 10 GB.
Envie arquivos grandes com segurança e criptografia de ponta a ponta
Transfira arquivos de até 10 GB gratuitamente com criptografia de ponta a ponta. Sem necessidade de conta. Seus arquivos são criptografados no navegador antes do envio — ninguém mais pode lê-los.
Enviar um arquivo