1. Separe autorização, transferência e publicação#
Um upload direto evita que o servidor da aplicação retransmita cada byte. O navegador pede permissão, o backend autoriza uma operação específica e o cliente transfere para o storage. Depois, a aplicação verifica o objeto e decide se ele pode ser usado. Esse último passo faz parte do fluxo, não é uma melhoria opcional.
Defina estados explícitos como pending, uploaded, scanning, ready e rejected. Uma linha ready precisa representar um objeto validado, não simplesmente uma resposta de sucesso do navegador. A interface pode mostrar o progresso sem prometer disponibilidade antes de a verificação terminar.
2. Assine uma chave criada pelo servidor#
Valide a sessão e a permissão para anexar arquivos ao recurso de destino. Monte a chave com um tenant autorizado e um identificador aleatório gerado no servidor. O nome original serve como metadado de exibição; ele não deve decidir o bucket nem permitir sobrescrever um objeto arbitrário.
session = requireVerifiedSession(request)
resource = authorizeAttachment(session, resourceId)
uploadId = randomId()
key = "quarantine/" + resource.tenantId + "/" + uploadId
recordPendingUpload(uploadId, resource, key, expectedSize)
url = signPut(privateBucket, key, shortExpiry, signedHeaders)
return { uploadId, url, requiredHeaders: signedHeaders }Uma URL assinada funciona como uma capacidade temporária: quem a tiver pode executar a operação permitida. Não a registre inteira em analytics ou logs. Use uma duração compatível com o tamanho do arquivo e preveja a renovação da permissão depois de autorizar o usuário de novo. As credenciais que assinam podem expirar antes do prazo solicitado.
Documentação: AWS: uso e validade de URLs pré-assinadas ↗
3. Defina limites que sejam realmente aplicados#
Um Content-Type enviado pelo cliente não comprova o formato do arquivo. Combine uma lista de tipos e extensões permitidos com inspeção do conteúdo, tamanho máximo e validação específica do formato. Para documentos compactados, considere também o tamanho descompactado e o consumo de CPU ao processá-los.
A forma de restringir um upload depende de PUT assinado, POST com policy e das capacidades do provedor compatível. Não assuma que todas as implementações de S3 aplicam as mesmas condições. Verifique quais headers fazem parte da assinatura e quais limites o storage valida; complete o que faltar numa verificação posterior sobre um objeto privado.
- Defina cota por usuário ou tenant e um limite de operações pendentes.
- Restrinja o CORS às origens e métodos da sua aplicação; CORS não substitui autorização.
- Mantenha o bucket privado e evite servir arquivos a partir da mesma origem da aplicação sem os controles adequados.
Documentação: OWASP: validação e armazenamento de uploads ↗
4. Verifique o que chegou ao storage#
O endpoint de finalização recebe o uploadId e resolve a chave a partir do registro pendente. Verifique de novo sessão, pertencimento e estado. Consulte os metadados do objeto para conferir o tamanho e as restrições verificáveis; não aceite como prova um ETag enviado pelo cliente nem o interprete universalmente como hash do arquivo.
Inspecione e analise o conteúdo em quarentena antes de torná-lo acessível. Uma URL de PUT pode ser reutilizada enquanto estiver válida; validar e depois servir a mesma chave mutável deixa uma janela para substituição. Vincule o processamento a uma versão específica quando o provedor permitir ou crie uma cópia privada de processamento que o cliente não consiga sobrescrever. Valide essa cópia e publique exatamente esse objeto.
| Estado | O que a aplicação pode fazer |
|---|---|
| pending / uploaded | Mostrar progresso e permitir verificação; não servir conteúdo. |
| scanning | Processar uma versão ou cópia imutável para o cliente. |
| ready | Autorizar leituras do objeto exato já validado. |
| rejected / expired | Informar a causa permitida e agendar a limpeza. |
Torne a finalização idempotente. Uma segunda chamada para o mesmo objeto já validado deve devolver o estado existente. Se a identidade do objeto mudou ou a permissão foi revogada, interrompa o fluxo.
5. Autorize também o download#
Ao ler um anexo privado, resolva a relação dele com o recurso e verifique o acesso atual. Um caminho difícil de adivinhar não é uma permissão. Você pode entregar uma URL de leitura temporária ou servir o arquivo por meio de um componente que aplique a autorização; escolha de acordo com o tamanho, a revogação necessária e a observabilidade.
Defina o Content-Disposition e um nome de download sanitizado. Para formatos ativos, considere uma origem separada e evite renderizar conteúdo arbitrário dentro da sua aplicação. Revise como o cache e os links compartilhados afetam o acesso quando um usuário sai de um workspace. Um link já emitido pode continuar funcionando até expirar.
6. Orce limpeza e recuperação#
Uploads abandonados ocupam espaço mesmo que ninguém chegue a clicar em salvar. Agende a limpeza de registros vencidos e objetos órfãos com uma margem que respeite transferências em andamento. Se você usa multipart, preveja abortar uploads incompletos. Mantenha rastreabilidade suficiente para distinguir um abandono de uma falha do provedor.
Estime armazenamento médio, operações, transferência, processamento e retenção de versões. O comparador normaliza tarifas de referência, mas alguns planos têm mínimos mensais e outros cobram classes de operações de forma diferente. Calcule um cenário com o seu tamanho médio de arquivo, downloads por arquivo e política de exclusão.
- Teste sessão expirada, permissão revogada e um upload de outro tenant.
- Teste tamanho incorreto, formato disfarçado e finalização repetida.
- Teste sobrescrita depois de iniciar a validação e queda do scanner.
- Verifique se objetos rejeitados e pendentes nunca ficam públicos.
Para se aprofundar: Custo real do armazenamento de objetos: S3 vs R2, B2 e Spaces
Documentação: Cloudflare R2: classes de operações e preços ↗ · DigitalOcean Spaces: mínimos e consumo ↗
Fontes e escopo
Documentação consultada em 25 de setembro de 2026. Os exemplos e critérios de decisão são propostas editoriais; adapte-os ao contrato da sua aplicação e valide-os no seu ambiente de testes autorizado.
Compare armazenamento de objetos
Confira preços, limites, condições e fontes de cada opção.
Abrir comparador