Échec d’envoi de fichier : trouvez la cause avant de réessayer
Lorsqu’un envoi échoue, ouvrez le panneau Réseau du navigateur et reproduisez l’échec une fois avec un petit fichier de test valide. Trouvez la requête d’envoi, examinez sa réponse et rapprochez-la des journaux serveur avant de modifier des limites ou d’ajouter des nouvelles tentatives. Ce guide s’adresse aux développeurs qui déboguent un outil d’envoi web existant ; vous devez avoir accès à son code de traitement des requêtes et à ses journaux pour confirmer la cause.
Capturer une tentative échouée
Ouvrez les DevTools avant l’envoi. Activez « Conserver le journal » si la soumission quitte la page, puis examinez l’URL, la méthode, le statut, la charge utile, la réponse et la durée de la requête. Le guide du panneau Réseau de Chrome indique où trouver ces informations. Vérifiez chaque requête du flux d’envoi : l’obtention d’une URL d’envoi, le transfert des octets et la finalisation de l’envoi peuvent échouer séparément.
Notez l’heure, la taille et le type du fichier, le statut et tout identifiant de requête fourni par le service. Utilisez cet identifiant pour corréler les journaux du proxy et de l’application. Sans identifiant, utilisez l’horodatage, la route et le compte de test. Excluez des rapports partagés les cookies, les en-têtes d’autorisation, les URL signées et le contenu des fichiers.
Comparez le fichier en échec avec un petit fichier du même format pris en charge. Si les deux échouent, la taille seule n’explique pas l’échec. Si seul le fichier le plus volumineux échoue, examinez les indices de taille et de durée avant de choisir entre une limite et une requête interrompue.
Localiser la couche en échec
Considérez le statut comme une piste. La réponse et les journaux correspondants identifient le composant qui a rejeté la requête ; un proxy et une application peuvent renvoyer le même statut.
| Ce que vous observez | Que vérifier ensuite |
|---|---|
| Aucune requête d’envoi n’apparaît | Validation côté client, sélection du fichier et exceptions JavaScript. Recherchez une requête antérieure en échec dans un flux en plusieurs étapes. |
401 ou 403 | Authentification, droit d’envoi, informations d’identification expirées et validation CSRF. Lisez le code d’erreur du service. |
413 | Limites de corps de requête au niveau du proxy et limites de fichier dans l’application. Trouvez le composant qui a journalisé le rejet. |
400, 415 ou 422 | Le nom de champ attendu, l’encodage de la requête et le résultat de la validation de fichier de l’application. |
fetch() est rejeté sans réponse lisible | Détails de la console du navigateur, CORS, erreurs de connexion et annulation. Vérifiez si le serveur a reçu la requête. |
500, 502, 503 ou 504 | Erreurs applicatives, disponibilité du serveur amont, délais d’expiration et erreurs de stockage dans les journaux serveur. |
Une réponse 2xx, mais aucun fichier exploitable | Contenu de la réponse, redirections, finalisation et statut de toute tâche de traitement. |
Ce sont des pistes d’investigation, pas une correspondance universelle entre statut et cause. Par
exemple, 413 signifie que le contenu de la requête est trop volumineux,
tandis que 503 décrit une indisponibilité temporaire du service ; ce
statut n’identifie pas un disque plein. Consultez les définitions des statuts HTTP.
Garder les échecs HTTP visibles dans votre code
fetch() se résout sur les réponses d’erreur HTTP.
Une promesse rejetée et une réponse avec ok: false sont des observations
différentes. Vérifiez response.ok avant d’analyser un corps : sinon, une page
d’erreur HTML renvoyée par un proxy peut devenir une erreur d’analyse JSON trompeuse.
Pour un gestionnaire d’envoi multipart existant, cette fonction utilitaire TypeScript préserve cette
distinction. Elle accepte le fichier sélectionné et l’URL de votre gestionnaire, et envoie un seul
champ nommé file. Utilisez-la uniquement si cela correspond à votre API ;
conservez l’authentification et la gestion CSRF requises par votre application lorsque vous adaptez
la requête. Le gestionnaire doit déjà être en cours d’exécution.
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
}
Passez le File sélectionné et l’URL d’envoi depuis votre gestionnaire de
soumission existant, attendez le résultat et gérez le rejet à cet endroit. Une sélection absente
n’envoie rien ; un fichier vide effectue tout de même une requête.
Upload returned HTTP 413 signifie qu’une réponse HTTP lisible est arrivée. Une erreur réseau
ou CORS du navigateur rejette l’appel fetch() lui-même et traverse cette
fonction utilitaire. La fonction utilitaire ne planifie pas de nouvelles tentatives. La réponse
renvoyée doit encore passer la validation de succès habituelle de votre API ; par exemple, une
redirection vers la connexion aboutissant à 200 ne prouve pas qu’un
fichier a été accepté.
Ne définissez pas Content-Type manuellement pour cette requête
FormData. Le navigateur fournit le délimiteur multipart ;
remplacer l’en-tête peut empêcher l’analyse.
Empêchez les soumissions en double tant que votre gestionnaire d’envoi existant est en attente.
Modifier le composant qui a rejeté l’envoi
Suivre une limite de taille le long du chemin de la requête
Supposons qu’un petit fichier réussisse et qu’un fichier plus volumineux reçoive
413. Si le proxy journalise le rejet et que l’application n’a aucune
requête correspondante, examinez d’abord le proxy. Vérifiez que la journalisation des requêtes de
l’application est activée avant de considérer l’absence d’entrée de journal comme une preuve.
Pour NGINX, client_max_body_size
limite le corps de la requête et peut être défini au niveau http,
server ou location. Vérifiez la configuration de la
route d’envoi réelle. Une requête multipart contient des champs et des délimiteurs en plus du
fichier ; une limite de corps de requête doit donc laisser de la marge au-delà de la taille de
fichier autorisée. Relever une limite de l’application ne peut pas supprimer une limite antérieure
du proxy.
Si la limite documentée du produit devrait admettre le fichier, ajustez la couche qui le rejette dans les limites de votre budget de stockage et de ressources. Sinon, conservez la limite et expliquez-la dans l’interface. Testez de nouveau le fichier d’origine, un fichier tout juste dans la taille autorisée et un fichier au-dessus. Ce dernier doit toujours être rejeté.
Lire le motif de rejet de l’application
Pour une réponse indiquant une requête mal formée ou un fichier non pris en charge, comparez la
requête avec le contrat du gestionnaire. Attend-il un champ multipart nommé
file, un autre nom de champ ou un corps brut ? La requête inclut-elle les
métadonnées requises ? Ne changez pas d’encodage et ne renommez pas l’extension du fichier tant que
la réponse ou le journal n’a pas identifié de discordance.
Si le format réel du fichier n’est pas pris en charge, choisissez une source prise en charge ou
convertissez-le avec un outil approprié. Remplacer .exe par
.jpg ne convertit pas le contenu. Testez de nouveau avec un fichier dont
la validité est connue et conservez un fichier interdit comme vérification négative.
Distinguer CORS d’une connexion interrompue
Une erreur fetch générique du navigateur n’identifie pas la cause. Examinez l’erreur précise de la console en parallèle du panneau Réseau et des journaux serveur.
- Si une requête préliminaire
OPTIONSéchoue, vérifiez l’origine, la méthode et les en-têtes de requête autorisés par le serveur. Le navigateur peut s’arrêter avant d’effectuer l’envoi. - Si l’envoi atteint le serveur mais que sa réponse ne contient pas les en-têtes CORS requis, JavaScript ne peut pas lire cette réponse. Le serveur a peut-être déjà accepté le fichier. Vérifiez l’état stocké avant de réessayer.
- Si le navigateur signale une erreur de connexion ou de certificat, examinez cette connexion. Si votre code a interrompu la requête, trouvez l’annulation ou le délai d’expiration qui l’a déclenchée.
Configurez CORS sur le serveur qui répond, y compris pour ses réponses d’erreur. Les requêtes
cross-origin avec informations d’identification nécessitent une origine autorisée explicite et les
paramètres d’identification appropriés ; * ne peut pas s’y substituer.
Le guide CORS de MDN explique les vérifications de la requête
préliminaire et de la réponse. Testez de nouveau depuis l’origine initiale du navigateur, avec les
conditions d’authentification initiales. Une requête cURL réussie ne prouve pas que CORS fonctionne
dans le navigateur.
N’utilisez pas mode: 'no-cors' comme correctif. Cela produit une réponse opaque dont
votre code ne peut examiner ni le statut ni le corps. Testez de nouveau à la fois un envoi accepté et
un rejet volontaire : les deux réponses doivent rester lisibles pour l’origine autorisée.
Remonter d’une erreur serveur à l’opération en échec
Une réponse 5xx nécessite une erreur côté serveur correspondante.
Déterminez si l’échec s’est produit pendant l’analyse de la requête, l’écriture d’un fichier
temporaire, le stockage de l’objet final ou un traitement ultérieur. Pour un stockage sur système de
fichiers, examinez l’espace libre, le quota, le chemin de destination réel et les permissions du
compte de service. Vérifiez aussi le stockage temporaire ; un répertoire final accessible en
écriture ne prouve pas que l’analyseur d’envoi puisse mettre des données en tampon sur disque.
Utilisez l’erreur sous-jacente pour choisir le correctif. Par exemple, les
erreurs EACCES et ENOENT
de Node distinguent un échec de permission d’un chemin manquant. Corrigez le chemin ou la permission
de service en cause, puis répétez le même envoi et vérifiez les octets stockés. Ne rendez pas le
répertoire d’envoi accessible en écriture à tous pour masquer un problème de permissions. Si une
passerelle signale un serveur amont indisponible, vérifiez l’état de l’application avant de modifier
les paramètres de disque ou les délais d’expiration.
Ajouter la reprise lorsque les interruptions sont en cause
Une fois que les envois valides fonctionnent, des interruptions de connexion répétées peuvent justifier des envois avec reprise. Avec tus, un client peut interroger le décalage stocké et reprendre à partir de là avec un serveur compatible. Découper un fichier en morceaux côté navigateur ne fournit pas à lui seul cet accord sur les décalages, le stockage et l’achèvement.
La capacité de reprise ne corrige pas un fichier invalide, une requête refusée, une configuration CORS ou un stockage épuisé. Si vous l’adoptez, testez l’interruption et la récupération, puis comparez le fichier complété avec l’original. Utilisez les implémentations tus pour choisir un client et un serveur compatibles.
Vérifier le correctif sans retirer les garde-fous
Exécutez de nouveau le cas d’échec d’origine, puis un petit fichier valide et un fichier délibérément interdit. Confirmez la réponse HTTP attendue, le résultat d’acceptation de l’application et le fichier stocké ou le résultat final du traitement. Pour un fichier envoyé sans transformation, comparez les octets téléchargés ou une somme de contrôle avec l’original. Une barre de progression terminée ne décrit que l’étape de transfert qu’elle mesure.
Conservez la validation de taille et de contenu côté serveur, même si l’interface vérifie d’abord. Traitez les noms de fichiers et les types MIME déclarés comme non fiables, générez les noms de stockage, restreignez l’accès et appliquez une analyse de sécurité ou une neutralisation de contenu lorsque le type de fichier et le risque l’exigent. Les recommandations de l’OWASP sur l’envoi de fichiers décrivent ces contrôles. Une erreur utile indique à l’utilisateur ce qu’il doit changer et fournit au support un identifiant de requête, tandis que les chemins internes, les traces de pile et les informations d’identification restent hors de la réponse.
