Ceci est un exemple CURL qui fonctionne bien:
curl -X POST \
<url> \
-H 'authorization: Bearer <token>' \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F [email protected] \
-F userId=<userId>
J'essaie de reproduire cette demande en utilisant 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
Afin de générer le file
passé à FormData
.
L'exemple précédent renvoie un code d'état HTTP 401
(Non autorisé) avec un message d'erreur indiquant que le userId
incorporé dans le jeton (envoyé via l'en-tête) ne correspond pas au userId
transmis de formData
.
Donc, je soupçonne que le FormData
qui arrive à l'API REST n'est pas correctement formé.
Le problème peut être lié à l'en-tête Content-Length
, Mais je n'ai pas trouvé de meilleur moyen de le calculer (si je n'utilise pas l'en-tête Content-Length
J'obtiens un 411
En-tête du code d'état HTTP Content-Length
Manquant).
Peut-être que cela échoue en raison d'une valeur incorrecte dans l'en-tête Content-Length
?
Avez-vous d'autres suggestions sur la raison de l'échec ou sur la meilleure façon de le déboguer?
Si des informations supplémentaires sont nécessaires pour clarifier ce problème, veuillez simplement 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 (erreur 401
Réponse du code d'état HTTP).
Si vous ouvrez votre inspecteur de réseau, exécutez cet extrait de code et soumettez le formulaire, vous devriez voir que le Content-Length
est défini correctement:
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>
Je me suis cogné la tête contre un mur similaire, en utilisant spécifiquement isomorphic-fetch
Sur le nœud pour POST un formulaire en plusieurs parties. La clé pour moi était de trouver .getHeaders()
. Notez que description NPM pour form-data
suggère que cela "fonctionnera" sans cela, mais cela ne semble pas, du moins pas dans le nœud (je pense que les navigateurs injectent des éléments d'en-tête?) .
// image is a Buffer containing a PNG image
// auth is the authorization token
const form_data = new FormData();
form_data.append("image", png, {
filename: `image.png`,
contentType: 'application/octet-stream',
mimeType: 'application/octet-stream'
});
const headers = Object.assign({
'Accept': 'application/json',
'Authorization': auth,
}, form_data.getHeaders());
try {
const image_res = await fetch(url, {
method: 'POST',
headers: headers,
body: form_data
});
if (!image_res.ok) {
const out = await image_res.json();
console.dir(out);
return;
}
}
catch (e) {
console.error(`Chart image generation exception: ${e}`);
}