0

Ceci est un exemple CURL qui fonctionne très bien:Comment POST avec en-tête multipart/form-data et FormData en utilisant fetch

curl -X POST \ 
    <url> \ 
    -H 'authorization: Bearer <token>' \ 
    -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ 
    -F [email protected] \ 
    -F userId=<userId> 

Je suis en train de reproduire cette demande à l'aide isomorphic-fetch.

J'ai essayé le code suivant:

const formData = new FormData(); 
formData.append('file', file); 
formData.append('userId', userId); 

return fetch(`<url>`, {  
    method: 'POST', 
    headers: { 
    'Content-Length': file.length 
    'Authorization: Bearer <authorization token>', 
    'Content-Type': 'multipart/form-data' 
    }, 
    body: formData 
})` 

J'utilise fs.readFileSync pour générer le file passé à FormData.

L'exemple précédent renvoie un code d'état 401 HTTP (non autorisé) avec un message d'erreur indiquant que le userId embarqué dans le jeton (envoyé par la tête) ne correspond pas au userId passé de formData.

Donc, ma suspicion est que le FormData qui arrive à l'API REST n'est pas formé de manière adéquate.

Le problème peut être lié avec l'en-tête Content-Length, mais je ne trouve pas une meilleure façon de le calculer (si je ne me l'en-tête Content-Length je reçois un en-tête de code d'état HTTP 411Content-Length manquant).

Le cas échéant, cela est dû à une valeur incorrecte dans l'en-tête Content-Length? Toutes les autres suggestions pour expliquer pourquoi cela échoue ou comment mieux le déboguer?

Si d'autres informations sont nécessaires pour clarifier ce problème, veuillez le demander.

MISE À JOUR

J'ai essayé le module form-data afin d'obtenir la bonne valeur Content-Length en utilisant la méthode formData.getLengthSync()

Cependant, le problème reste le même (401 erreur réponse de code d'état HTTP).

+0

Drop the L'en-tête de demande Content-Type doit être généré automatiquement par le navigateur pour inclure la limite multi-parties. Je pense que si vous laissez tomber cela et les en-têtes 'Content-Length' vous devriez être d'accord. – idbehold

+0

Je l'ai déjà essayé sans succès, quand je n'envoie pas l'en-tête 'Content-Length',' API' renvoie une erreur '411': code d'état HTTP:' Le serveur refuse d'accepter la requête sans contenu défini. Length' – rfc1484

+0

Essayez de définir la longueur du contenu à 12345. Le serveur sur lequel vous téléchargez n'est pas très bien conçu. – idbehold

Répondre

2

Si vous ouvrez votre inspecteur réseau, exécutez cet extrait de code, et soumettre le formulaire, vous devriez voir que le Content-Length est correctement réglée:

const foo = document.getElementById('foo') 
 
foo.addEventListener('submit', (e) => { 
 
    e.preventDefault() 
 
    const formData = new FormData(foo) 
 
    formData.append('userId', 123) 
 
    fetch('//example.com', { 
 
    method: 'POST', 
 
    body: formData 
 
    }) 
 
})
<form id="foo"> 
 
    <input id="file" type="file" name="file"/><br><br> 
 
    <button type="submit">Submit</button> 
 
</form>

+0

Donc si je comprends bien le problème n'est pas avec l'implémentation du client mais avec l'implémentation de l'API REST (ce qui signifie qu'il ne doit pas renvoyer un code d'erreur HTTP '411' quand l'en-tête 'Content-Length' n'est pas passé) – rfc1484

+0

rfc1484 Je dis que le seul en-tête que vous devriez spécifier dans votre configuration 'fetch()' est l'en-tête 'Authorization' car les en-têtes' Content-Length' et 'Content-Type' seront automatiquement définis par le navigateur. Alors s'il vous plaît essayez simplement de supprimer ces deux lignes de votre code. – idbehold

+0

Je comprends, mais j'ai déjà essayé cette solution et cela n'a pas fonctionné (elle renvoyait l'erreur '411' mentionnée auparavant). Puisque je teste ceci en utilisant un test unitaire, je pense que le problème est que la requête est effectuée côté serveur, donc peut être dans ce cas les en-têtes ne seront pas définis automatiquement par le navigateur, car il ne passe pas par un browser et utilise la bibliothèque 'node-fetch' directement (la bibliothèque sous-jacente utilisée par' isomorphic-fetch' lors de l'exécution de requêtes côté serveur). Donc peut-être cela fonctionnera "côté client" bien que le test unitaire échoue actuellement. – rfc1484