Falha no upload de arquivo: identifique a causa antes de repetir
Quando um upload falhar, abra o painel Rede do navegador e reproduza a falha uma vez com um arquivo de teste pequeno e válido. Localize a requisição de upload, examine a resposta e correlacione-a com os logs do servidor antes de alterar limites ou adicionar novas tentativas. Este guia é para desenvolvedores que depuram um componente de upload web existente; você precisa de acesso ao código que trata as requisições e aos logs para confirmar a causa.
Capture uma tentativa que falhou
Abra o DevTools antes de fazer o upload. Ative Manter registro se o envio navegar para outra página e examine a URL, o método, o status, o payload, a resposta e os tempos da requisição. O guia do painel Rede do Chrome mostra onde encontrar esses detalhes. Verifique todas as requisições do fluxo de upload: a obtenção de uma URL de upload, a transferência de bytes e a finalização do upload podem falhar separadamente.
Registre o horário, o tamanho e o tipo do arquivo, o status e qualquer ID de requisição fornecido pelo serviço. Use esse ID para correlacionar os logs do proxy e da aplicação. Sem um ID, use o carimbo de data e hora, a rota e a conta de teste. Não inclua cookies, cabeçalhos de autorização, URLs assinadas nem o conteúdo dos arquivos nos relatórios compartilhados.
Compare o arquivo cujo upload falha com um arquivo pequeno do mesmo formato compatível. Se ambos falharem, o tamanho por si só não explica a falha. Se apenas o arquivo maior falhar, examine as evidências de tamanho e duração antes de concluir se a causa é um limite ou uma requisição interrompida.
Localize a camada que falhou
Trate o status como uma pista. A resposta e os logs correspondentes identificam qual componente rejeitou a requisição; um proxy e uma aplicação podem retornar o mesmo status.
| O que você observa | O que verificar em seguida |
|---|---|
| Nenhuma requisição de upload aparece | Validação no cliente, seleção de arquivos e exceções de JavaScript. Verifique se uma requisição anterior falhou em um fluxo de várias etapas. |
401 ou 403 | Autenticação, permissão de upload, credenciais expiradas e validação de CSRF. Leia o código de erro do serviço. |
413 | Limites do corpo da requisição no proxy e limites de arquivos na aplicação. Localize o componente que registrou a rejeição. |
400, 415 ou 422 | O nome de campo esperado, a codificação da requisição e o resultado da validação do arquivo pela aplicação. |
fetch() rejeita sem uma resposta legível | Detalhes no console do navegador, CORS, erros de conexão e cancelamento. Verifique se o servidor recebeu a requisição. |
500, 502, 503 ou 504 | Erros da aplicação, disponibilidade do serviço upstream, tempos limite e erros de armazenamento nos logs do servidor. |
Uma resposta 2xx, mas nenhum arquivo utilizável | Conteúdo da resposta, redirecionamentos, finalização e status de qualquer tarefa de processamento. |
Esses são caminhos de investigação, não uma correspondência universal entre status e causa. Por
exemplo, 413 significa que o conteúdo da requisição é grande demais,
enquanto 503 descreve uma indisponibilidade temporária do serviço; isso
não identifica um disco cheio. Consulte as
definições dos status HTTP.
Mantenha as falhas HTTP visíveis no seu código
fetch() resolve mesmo com respostas de erro HTTP.
Uma promessa rejeitada e uma resposta com ok: false são observações diferentes.
Verifique response.ok antes de analisar o corpo: caso contrário, uma página de
erro HTML de um proxy pode se transformar em um erro enganoso de análise de JSON.
Para um manipulador de upload multipart existente, esta função auxiliar em TypeScript preserva
essa distinção. Ela recebe o arquivo selecionado e a URL do manipulador e envia um campo chamado
file. Use-a apenas quando isso corresponder à sua API; ao adaptar a
requisição, mantenha o tratamento de autenticação e CSRF exigido pela aplicação. O manipulador já
deve estar em execução.
async function uploadForDiagnosis(
file: File | undefined,
url: string,
): Promise<Response | undefined> {
if (file === undefined) return
const body = new FormData()
body.append('file', file)
const response = await fetch(url, { method: 'POST', body })
if (!response.ok) {
throw new Error(`Upload returned HTTP ${response.status}`)
}
return response
}
Passe o File selecionado e a URL de upload a partir do manipulador de envio
existente, aguarde o resultado e trate a rejeição ali. Sem uma seleção, nada é enviado; um arquivo
vazio ainda gera uma requisição. Upload returned HTTP 413 significa que uma resposta HTTP
legível chegou. Um erro de rede ou CORS no navegador rejeita o próprio
fetch() e se propaga por esta função auxiliar. A função não agenda novas
tentativas. A resposta retornada ainda precisa passar pela validação normal de sucesso da sua API;
um redirecionamento para login que termina em 200, por exemplo, não
comprova que o arquivo foi aceito.
Não defina Content-Type manualmente para esta requisição
FormData. O navegador fornece o delimitador multipart;
sobrescrever o cabeçalho pode impedir a análise correta.
Mantenha os envios duplicados desativados enquanto o manipulador de upload existente estiver pendente.
Altere o componente que rejeitou o upload
Rastreie um limite de tamanho pelo caminho da requisição
Suponha que o upload de um arquivo pequeno tenha sucesso e o de um maior receba
413. Se o proxy registrar a rejeição e a aplicação não tiver uma requisição
correspondente, investigue o proxy primeiro. Confirme que o registro de requisições da aplicação está
ativado antes de tratar a ausência de uma entrada no log como evidência.
No NGINX, client_max_body_size
limita o corpo da requisição e pode ser definido no nível http,
server ou location. Verifique a configuração da rota
real de upload. Uma requisição multipart contém campos e delimitadores além do arquivo, portanto
um limite do corpo da requisição precisa de uma margem além do tamanho permitido para o arquivo.
Aumentar um limite da aplicação não remove um limite anterior do proxy.
Se o limite documentado do produto deveria permitir o arquivo, ajuste a camada que o rejeitou dentro do seu orçamento de armazenamento e recursos. Caso contrário, mantenha o limite e explique-o na interface. Teste novamente o arquivo original, um arquivo com tamanho logo abaixo do limite permitido e outro acima dele. O último ainda deve ser rejeitado.
Leia o motivo da rejeição pela aplicação
Para uma resposta de requisição malformada ou arquivo não compatível, compare a requisição com o
contrato do manipulador. Ele espera um campo multipart chamado file, um
campo com outro nome ou um corpo bruto? A requisição inclui os metadados obrigatórios? Não troque a
codificação nem renomeie a extensão do arquivo até que a resposta ou o log identifique uma
incompatibilidade.
Se o formato real do arquivo não for compatível, escolha um arquivo de origem compatível ou
converta-o com uma ferramenta adequada. Alterar .exe para
.jpg não converte o conteúdo. Teste novamente com um arquivo que você sabe
ser válido e mantenha um arquivo não permitido como teste negativo.
Diferencie CORS de uma conexão interrompida
Um erro genérico de fetch no navegador não identifica a causa. Examine o erro específico do console junto com o painel Rede e os logs do servidor.
- Se uma requisição preflight
OPTIONSfalhar, verifique a origem, o método e os cabeçalhos de requisição permitidos pelo servidor. O navegador pode parar antes de enviar o upload. - Se o upload chegar ao servidor, mas a resposta não tiver os cabeçalhos CORS obrigatórios, o JavaScript não poderá ler essa resposta. O servidor pode já ter aceitado o arquivo. Verifique o estado armazenado antes de tentar novamente.
- Se o navegador relatar um erro de conexão ou certificado, investigue essa conexão. Se o seu código abortou a requisição, localize o cancelamento ou o tempo limite que causou isso.
Configure o CORS no servidor que responde, inclusive nas respostas de erro. Requisições entre
origens com credenciais precisam de uma origem permitida explícita e das configurações de
credenciais adequadas; * não substitui isso. O
guia de CORS da MDN explica as verificações de preflight e de
resposta. Teste novamente a partir da origem original do navegador, com as condições de
autenticação originais. Uma requisição cURL bem-sucedida não comprova que o CORS funciona no navegador.
Não use mode: 'no-cors' como correção. Isso produz uma resposta opaca cujo status e
corpo seu código não pode examinar. Teste novamente tanto um upload aceito quanto uma rejeição
intencional: ambas as respostas devem continuar legíveis para a origem permitida.
Rastreie um erro do servidor até a operação que falhou
Uma resposta 5xx precisa de um erro correspondente no lado do servidor.
Identifique se a falha ocorreu ao analisar a requisição, gravar um arquivo temporário, armazenar o
objeto final ou executar um processamento posterior. Para armazenamento no sistema de arquivos,
examine o espaço livre, a cota, o caminho real de destino e as permissões da conta de serviço.
Verifique também o armazenamento temporário; um diretório final com permissão de gravação não
comprova que o analisador de upload consegue gravar dados temporariamente em disco.
Use o erro subjacente para escolher a correção. Por exemplo, os
erros EACCES e ENOENT
do Node distinguem uma falha de permissão de um caminho inexistente. Corrija o caminho ou a
permissão específica do serviço, repita o mesmo upload e verifique os bytes armazenados. Não
conceda permissão de gravação a todos no diretório de upload para ocultar um problema de permissões.
Se um gateway relatar que um serviço upstream está indisponível, confirme a integridade da aplicação
antes de alterar as configurações de disco ou os tempos limite.
Adicione retomada quando o problema forem interrupções
Quando os uploads válidos estiverem funcionando, interrupções repetidas de conexão podem justificar uploads retomáveis. Com o tus, um cliente pode consultar o offset armazenado e continuar a partir dele usando um servidor compatível. Apenas dividir um arquivo em partes no navegador não estabelece esse acordo sobre offsets, armazenamento e conclusão.
A capacidade de retomada não corrige um arquivo inválido, uma requisição negada, a configuração de CORS nem a falta de espaço de armazenamento. Se você a adotar, teste a interrupção e a recuperação e compare o arquivo concluído com o original. Use as implementações de tus para escolher um cliente e um servidor compatíveis.
Verifique a correção sem remover as proteções
Execute novamente o caso original que falhou, depois teste um arquivo pequeno válido e um arquivo deliberadamente não permitido. Confirme a resposta HTTP esperada, o resultado de aceitação pela aplicação e o arquivo armazenado ou o resultado final do processamento. Para um upload sem alterações, compare os bytes baixados ou uma soma de verificação com o original. Uma barra de progresso concluída descreve apenas a etapa de transferência que ela mede.
Mantenha a validação de tamanho e conteúdo no lado do servidor, mesmo que a interface faça a verificação primeiro. Trate nomes de arquivos e tipos MIME declarados como não confiáveis, gere nomes para armazenamento, restrinja o acesso e aplique varredura de segurança ou neutralização de conteúdo quando o tipo de arquivo e o risco exigirem. As orientações da OWASP para upload de arquivos descrevem esses controles. Um erro útil informa ao usuário o que alterar e fornece ao suporte um ID de requisição, enquanto caminhos internos, rastreamentos de stack e credenciais ficam fora da resposta.
