Axios: La requĂȘte POST fonctionne dans le navigateur mais pas sur le nƓud

CrĂ©Ă© le 20 juil. 2017  Â·  26Commentaires  Â·  Source: axios/axios

Semblable Ă  #318 , je ne parviens pas Ă  faire une demande de publication avec axios sur node. Mais sur le navigateur, le mĂȘme morceau de code semble fonctionner correctement.

const fdata = new FormData();
fdata.append('user', u);
fdata.append('hostnames', n.join(' '));
const host = localStorage.getItem('host');
const port = localStorage.getItem('port');
axios({
  url: `http://${host}:${port}/hosts/remove`,
  method: 'post',
  data: fdata
}).then(response => {
  if (response.status === 200) {
    console.log(response.data);
    console.log('Removed host successfully');
  }
  return null;
}).catch(er => console.log(er));

Avec unirest ça marche :

unirest.post(`http://${host}:${port}/hosts/remove`)
.headers({ 'Content-Type': 'multipart/form-data' })
.field('user', u)
.field('hostnames', h.join(' '))
.end(response => {
  console.log(response.body);
});
  • version axios : v0.16.2
  • Environnement : nƓud v8.0.0, windows 8.1

Commentaire le plus utile

Cela pourrait ĂȘtre considĂ©rĂ© comme un doublon de #789.

J'ai pu utiliser le package form-data avec Axios dans nodejs. Il fournit essentiellement une interface de type FormData . Vous devez cependant faire attention Ă  transmettre manuellement les en-tĂȘtes qu'il gĂ©nĂšre Ă  Axios. Par exemple:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result

  console.log(result.data);
});

Tous les 26 commentaires

Cela pourrait ĂȘtre considĂ©rĂ© comme un doublon de #789.

J'ai pu utiliser le package form-data avec Axios dans nodejs. Il fournit essentiellement une interface de type FormData . Vous devez cependant faire attention Ă  transmettre manuellement les en-tĂȘtes qu'il gĂ©nĂšre Ă  Axios. Par exemple:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result

  console.log(result.data);
});

Oui, j'ai essayé avec ce package form-data . Eh bien, c'est bon maintenant, j'ai changé l'API cÎté serveur pour analyser JSON à la place.

quelqu'un peut-il s'il vous plaĂźt montrer ce qui doit ĂȘtre fait dans l'application nodejs ??

@ ar412 J'ai essayé de donner un exemple sur https://github.com/mzabriskie/axios/issues/1006#issuecomment -320165427, pourriez-vous clarifier ce que vous demandez ?

@binki si axios est utilisé pour envoyer une demande de publication à une restapi avec des données, alors comment récupérer ces données dans l'api de repos (qui se trouve dans une application express).

vous pouvez essayer ceci https://expressjs.com/en/4x/api.html#req @ar412

@ar412 Pour recevoir des données en plusieurs busboy comme recommandé par body-parser 's docs . Fondamentalement, pour apprendre à gérer les fichiers téléchargés dans Express, ce n'est pas du tout lié à Axios, vous feriez donc mieux de demander ailleurs car vous avez détourné ce fil ;-). Par exemple, voir cette réponse sur SO .

Message d'erreur reçu : form.getHeaders() n'est pas une fonction

@binki
Hey! J'ai un serveur hapi.js dans lequel je veux POSTER un fichier image stocké dans une variable en utilisant fs.readFile(chemin).
Je ne parviens pas Ă  le faire fonctionner en envoyant cela en tant que FormData()

C'est mon code :

fs.readFile(__dirname+'/../static/lisa_server.jpg', (error, imageData) => {
          var form = new FormData()

            form.append('file', imageData,  {
            filename: 'unicycle.jpg', // ... or:
            filepath: '/../static/lisa_server.jpg',
            contentType: 'image/jpg',
            knownLength: 19806
          })

Ensuite, j'envoie le formulaire comme corps de la demande et je définis les options['Content-Type'] = 'multipart/form-data'

Pourriez-vous aider?
TrÚs appréciée!

@bstolarz si vous passez un Buffer , ce que vous faites, vous n'avez pas besoin de passer knownLength . De plus, si vous lisez ce que vous avez Ă©crit (euh, copiĂ© et collĂ© Ă  partir des exemples de README de filename ou filepath — pas les deux. Les seules choses qu'il pourrait ĂȘtre judicieux pour vous de dĂ©finir sont :

  1. filename OU filepath
  2. contentType (au cas oĂč le serveur requiert une valeur de type de contenu particuliĂšre, sinon cela peut probablement ĂȘtre omis).

Ce que je parie, c'est que la taille de l'image que vous envoyez a une taille qui n'est pas 19806 parce que cette 19806 est quelque chose que vous avez copiĂ© Ă  partir d'un exemple dans form-data s » docs plutĂŽt que calculĂ©s pour vos propres donnĂ©es. Cela est susceptible de provoquer une erreur de form-data ou d'Ă©crire des donnĂ©es invalides dans la requĂȘte HTTP. Avez-vous vĂ©rifiĂ© si le axios.post() renvoyĂ© Promise est un rejet ou si une exception est levĂ©e ? Si la requĂȘte axios est rejetĂ©e, vĂ©rifiez si l'objet d'erreur a une clĂ© result et, si c'est le cas, vĂ©rifiez quelle est la err.result.status . S'il s'agit d'une valeur 4xx autre que 404 ou 403, cela signifie probablement que le serveur rejette une requĂȘte mal formĂ©e qui pourrait rĂ©sulter d'une taille connue incorrecte.

@binki
Hé, merci pour votre réponse. J'ai corrigé les choses que vous avez mentionnées, donc maintenant mon code est

fs.readFile(__dirname+'/../static/lisa_server.jpg', (error, imageData) => {
          var form = new FormData()

          form.append('file', imageData, {
               filepath: __dirname+'/../static/lisa_server.jpg',
               contentType: 'image/jpg'

          })

Mais le serveur renvoie 411 "La longueur est requise" (j'ai Ă©galement essayĂ© fs.createReadStream qui semble ĂȘtre entiĂšrement pris en charge par FormData, mais j'obtiens la mĂȘme erreur de longueur).

@binki
J'ai rĂ©ussi Ă  dĂ©finir la longueur du contenu de l'en-tĂȘte dans la couche la plus basse et je n'obtiens plus cette erreur.
Maintenant que je ne reçois pas de 411 du serveur, je suis revenu à l'erreur que j'avais une fois 400 - "Aucun fichier fourni".

Voici Ă  quoi ressemble la demande

Demande de départ

{ adapter: [Function: httpAdapter],
  transformRequest: { '0': [Function: transformRequest] },
  transformResponse: { '0': [Function: transformResponse] },
  timeout: 5000,
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
  maxContentLength: -1,
  validateStatus: [Function: validateStatus],
  headers:
   { common: { Accept: 'application/json, text/plain, */*' },
     delete: {},
     get: {},
     head: {},
     post: { 'Content-Type': 'application/json' },
     put: { 'Content-Type': 'application/json' },
     patch: { 'Content-Type': 'application/json' },
     'User-Agent': 'trojan server 1.0',
     'X-Origin-Panamera': 'Staging',
     'Content-Length': 25247 },
  baseURL: 'https://letgoar-a.akamaihd.net/api/v1',
  method: 'post',
  url: 'https://<baseDomain>/api/v1/images',
  data:
   FormData {
     _overheadLength: 218,
     _valueLength: 25247,
     _valuesToMeasure: [],
     writable: false,
     readable: true,
     dataSize: 0,
     maxDataSize: 2097152,
     pauseStreams: true,
     _released: false,
     _streams:
      [ '----------------------------677738213014296377492349\r\nContent-Disposition: form-data; name="file"; filename="/Users/brenda/repos/qreator2/qreator/trojan-server/src/static/lisa_server.jpg"\r\nContent-Type: image/jpg\r\n\r\n',
        <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e2 11 2c 49 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 11 1c 61 70 70 6c 02 00 00 00 ... >,
        [Function: bound ] ],
     _currentStream: null,
     _boundary: '--------------------------677738213014296377492349' },
  'Content-Type': 'multipart/form-data' }

J'espÚre que vous vérifiez cela. Pour vous, cela ressemble-t-il à une demande raisonnable ?

Merci d'avance

@bstolarz J'ai fait de mon mieux pour reproduire votre problĂšme. Cependant, je ne peux pas. J'ai Ă©crit ce code pour essayer d'imiter ce que vous faites. Cependant, j'ai volontairement omis de dĂ©finir manuellement Content-Length . Je suis convaincu que le fait que vous paramĂ©triez Content-Length pourrait ĂȘtre liĂ© Ă  votre problĂšme. Veuillez essayer de laisser le form-data s'occuper de calculer cela pour vous—c'est pourquoi vous devez appeler form.getHeaders() .

Voir cette pĂąte : https://gist.github.com/binki/10ac3e91851b524546f8279733cdadad . Peut-ĂȘtre pouvez-vous modifier la façon dont vous appelez axios.post() ou axios() pour correspondre Ă  mon exemple et cela fonctionnera pour vous ?

Si vous rencontrez toujours des problĂšmes, essayez de dĂ©placer votre code vers son propre script et de le reproduire lĂ -bas. Cela peut vous aider Ă  rĂ©soudre le problĂšme. Si vous ĂȘtes toujours bloquĂ©, veuillez publier le code complet, y compris l'appel Ă  axios() ou axios.post() en guise d'essentiel et le lier ici et, si je peux, je l'examinerai.

ça ne marche toujours pas du tout...

@rodrigogs Si vous voulez de l'aide, vous devrez ĂȘtre plus dĂ©taillĂ© ;-).

J'ai suivi cette recherche utile sur Axios et la solution finale fonctionne pour moi ( lien )

En voici le copier/coller :

import fs from 'fs';
import FormData from 'form-data';
import axios from 'axios';

let data = fs.createReadStream(__dirname + '/test.jpg');
let form = new FormData();

form.append('type','image');
form.append('media',data,'test.jpg');

function getHeaders(form) {
    return Promise((resolve, reject) => {
        form.getLength((err, length) => {
            if(err) { reject(err); }
            let headers = Object.assign({'Content-Length': length}, form.getHeaders());
            resolve(headers);
         });
    });
}

getHeaders(form)
.then((headers) => {
    return axios.post(url, form, {headers:headers})
})
.then((response)=>{
    console.log(response.data)
})
.catch(e=>{console.log(e)})

@westofpluto , j'obtiens aussi la mĂȘme erreur. @binki , des idĂ©es ?
L'erreur
form.getHeaders n'est pas une fonction

@smplyjr Pouvez-vous donner plus de contexte et me dire comment vous obtenez form ? Sans code, nous ne pouvons pas dire ce que vous faites ou vous aider.

Pour les utilisateurs de nodejs, rĂ©solvez en utilisant la bibliothĂšque de chaĂźne de requĂȘte, comme suit :

const querystring = require('querystring')
axios
  .post(URL, querystring.stringify(data))
  .then((response) => ...)
  .catch((error) => ...)

Comme @heldrida l'a mentionnĂ©, utilisez la chaĂźne de requĂȘte. C'est ainsi qu'axios recommande de procĂ©der ici : https://www.npmjs.com/package/axios#nodejs. Le package form-data a toutes sortes de problĂšmes ici et vous finirez par vous arracher les cheveux en essayant de le faire fonctionner.

@heldrida @ashok-sc Comment dois-je utiliser querystring ou qs pour télécharger un fichier avec axios ? J'utilise axios pour télécharger des fichiers à partir d'un AWS Lambda et je n'ai évidemment pas accÚs à l'objet File à partir de là

@bstolarz J'ai fait de mon mieux pour reproduire votre problĂšme. Cependant, je ne peux pas. J'ai Ă©crit ce code pour essayer d'imiter ce que vous faites. Cependant, j'ai volontairement omis de dĂ©finir manuellement Content-Length . Je suis convaincu que le fait que vous paramĂ©triez Content-Length pourrait ĂȘtre liĂ© Ă  votre problĂšme. Veuillez essayer de laisser le form-data s'occuper de calculer cela pour vous—c'est pourquoi vous devez appeler form.getHeaders() .

Voir cette pĂąte : https://gist.github.com/binki/10ac3e91851b524546f8279733cdadad . Peut-ĂȘtre pouvez-vous modifier la façon dont vous appelez axios.post() ou axios() pour correspondre Ă  mon exemple et cela fonctionnera pour vous ?

Si vous rencontrez toujours des problĂšmes, essayez de dĂ©placer votre code vers son propre script et de le reproduire lĂ -bas. Cela peut vous aider Ă  rĂ©soudre le problĂšme. Si vous ĂȘtes toujours bloquĂ©, veuillez publier le code complet, y compris l'appel Ă  axios() ou axios.post() en guise d'essentiel et le lier ici et, si je peux, je l'examinerai.

Merci mec. L'ajout de Content-Length a résolu mon problÚme maintenant, je peux utiliser les appels axios backend-2-backend avec FormData :
const options = { method: 'POST', url: myUrl, data: justJsonBody, transformRequest: [function (data, headers) { const formData = convertToFormData(data); // returrns ForrmData from form-data headers['Content-Type'] = formData.getHeaders()['content-type']; headers['Content-Length'] = formData._overheadLength; return formData; }] };

Cela pourrait ĂȘtre considĂ©rĂ© comme un doublon de #789.

J'ai pu utiliser le package form-data avec Axios dans nodejs. Il fournit essentiellement une interface de type FormData . Vous devez cependant faire attention Ă  transmettre manuellement les en-tĂȘtes qu'il gĂ©nĂšre Ă  Axios. Par exemple:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result

  console.log(result.data);
});

Une autre façon ici. De cette façon, vous pouvez ajouter un agent proxy à et à d'autres configurations :

const axios = require('axios');
const FormData = require('form-data');
const ProxyAgent = require('proxy-agent');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios({
  method: 'POST',
  url: 'http://example.org/endpoint',
  data: form,
  agent: new ProxyAgent("https://username:[email protected]:8080"),
  headers: bodyFormData.getHeaders()
}).then(result => {
  // Handle result

  console.log(result.data);
});

Cela fonctionne pour moi.

// ES6
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';

FormData.prototype.getHeadersWithContentLength = function getHeadersWithContentLength() {
  return new Promise((resolve, reject) => {
    this.getLength((err, length) =>
      err ? reject(err) : resolve({ ...this.getHeaders(), 'Content-Length': length })
    )
  })
}

const payload = new FormData();
const form = new formidable.IncomingForm();

form.parse(req, (err, fields, { file }) => {
  if (err) return;

  payload.append("file", fs.createReadStream(file.path), {
    filename: file.name,
    contentType: file.type
  });

  payload.getHeadersWithContentLength().then(headers => {
    api
      .post(endpoint, payload, { headers })
      .then(({ data }) => data)
      .then(data => res.json({ data }));
  });
});

Merci Ă  tous les contributeurs de cet article. AprĂšs avoir passĂ© des heures Ă  avoir des problĂšmes pour publier mon formulaire form-data aide d'Axios, sur un backend qui le publie dans un compartiment Amazon, la solution s'est avĂ©rĂ©e ĂȘtre de dĂ©finir manuellement content-length ....

Pour tous ceux qui ont des problĂšmes avec mon code, cela peut peut-ĂȘtre aider le prochain Ă  avoir des problĂšmes pour que cela fonctionne :)

const axios = require('axios');
const FormData = require('form-data');

// Where buffer is a file
formData.append('file', buffer);

// Added a promise version like seen in earlier comments to get this
const contentLength = await formData.getLength();

await axios(`<ENDPOINT>`, {
    method: 'POST',
    baseURL: <BASE_URL>,
    params: {
        fileName: '<FILE_NAME>.png'
    },
    headers: {
        authorization: `Bearer <TOKEN>`,
        ...formData.getHeaders(),
        'content-length': contentLength
    },
    data: formData
});

AprĂšs avoir passĂ© des heures Ă  avoir des problĂšmes pour publier mon formulaire form-data aide d'Axios, sur un backend qui le publie dans un compartiment Amazon, la solution s'est avĂ©rĂ©e ĂȘtre de dĂ©finir manuellement content-length ....

Oui. Un de mes collĂšgues et moi avons Ă©galement passĂ© plusieurs heures Ă  essayer de poster des fichiers sur un backend qui rĂ©pondrait qu'aucune donnĂ©e n'Ă©tait soumise, alors que c'Ă©tait Ă©videmment le cas, car nous pouvions suivre la demande et voir le contenu. Le problĂšme Ă©tait l'en-tĂȘte de longueur de contenu manquant.

A noter, si vous ajoutez un tampon au FormData, c'est bien si vous appelez formData.getLengthSync() mais si vous avez affaire Ă  un flux, vous devez d'abord stat le fichier avec fs.statSync(filePath).size ou obtenir la taille complĂšte d'une autre maniĂšre (comme Ă  partir d'un en-tĂȘte de longueur de contenu d'un amont), par exemple si le flux provient d'une requĂȘte ou d'un socket ou autre. Si votre flux provient du disque Ă  la place, fs.statSync(filePath).size donnera la taille en octets, vous pouvez donc l'ajouter dansknownLength lors de l'ajout Ă  FormData :

formData.append("file", fs.createReadStream(filePath), { filename: 'whatever.pdf', knownLength: fs.statSync(filePath).size });

Bien sĂ»r, toutes les mĂ©thodes de synchronisation peuvent ĂȘtre remplacĂ©es par des mĂ©thodes asynchrones et le mot-clĂ© wait.

// Added a promise version like seen in earlier comments to get this
const contentLength = formData.getLength();

Je suppose que vous avez oublié un await avant formData en effet...

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

shaosh picture shaosh  Â·  3Commentaires

achingbrain picture achingbrain  Â·  3Commentaires

ghost picture ghost  Â·  3Commentaires

reggi picture reggi  Â·  3Commentaires

Spartano picture Spartano  Â·  3Commentaires