axios post demande d'envoyer des données de formulaire


204

La POSTrequête axios atteint l'URL du contrôleur mais définit des valeurs nulles pour ma classe POJO, lorsque je passe par les outils de développement dans Chrome, la charge utile contient des données. Qu'est-ce que je fais mal?

Demande Axios POST:

var body = {
    userName: 'Fred',
    userEmail: 'Flintstone@gmail.com'
}

axios({
    method: 'post',
    url: '/addUser',
    data: body
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

Réponse du navigateur:

entrez la description de l'image ici

Si je définis les en-têtes comme:

headers:{
  Content-Type:'multipart/form-data'
}

La requête renvoie l'erreur

Erreur lors de la publication des données en plusieurs parties / formulaire. L'en-tête Content-Type n'a pas de limite

Si je fais la même demande dans postman, cela fonctionne bien et définit les valeurs de ma classe POJO.

Quelqu'un peut-il expliquer comment définir une limite ou comment envoyer des données de formulaire en utilisant axios.

Réponses:


328

Vous pouvez publier des données axios en utilisant FormData () comme:

var bodyFormData = new FormData();

Et puis ajoutez les champs au formulaire que vous souhaitez envoyer:

bodyFormData.set('userName', 'Fred');

Si vous téléchargez des images, vous souhaiterez peut-être utiliser .append

bodyFormData.append('image', imageFile); 

Et puis vous pouvez utiliser la méthode axios post (vous pouvez la modifier en conséquence)

axios({
    method: 'post',
    url: 'myurl',
    data: bodyFormData,
    headers: {'Content-Type': 'multipart/form-data' }
    })
    .then(function (response) {
        //handle success
        console.log(response);
    })
    .catch(function (response) {
        //handle error
        console.log(response);
    });

Vous pouvez en lire plus ici


8
bodyFormData.set n'est pas une fonction que j'ai eu cette erreur
Manoj Bhardwaj

10
Vous devez utiliser append au lieu de set.
Pratik Singhal

1
@ManojBhardwaj vous devez lier la fonction, supposez que si vous faites une demande à l'intérieur de la fonction de soumission, vous devez lier cette fonction. ex: - onSubmit = {this.submit (bind (this)} ou ex: - dans le constructeur constructeur (super) {this.submit = this.submit.bind (this);} submit () {axios ({}) ; ...}
Srikanth Gowda

bodyFormData.append fonctionne aussi pour moi. Je ne sais pas pourquoi setne pas travailler
Im Batman

1
Votre objet de configuration est incorrect. Cela devrait être:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor

35

Découvrez la chaîne de requête .

Vous pouvez l'utiliser comme suit:

var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));

4
C'est encore mieux dans un environnement de noeud
Jjagwe Dennis

Si vous avez des objets imbriqués dans vos données, 'chaîne de requête' peut ne pas fonctionner comme prévu. Dans ce cas, vous pouvez utiliser le module 'qs' pour stringifier les données.
Zihad Ul Islam

33

Dans mon cas, j'ai dû ajouter la limite à l'en- tête comme suit:

const form = new FormData();
    formData.append(item.name, fs.createReadStream(pathToFile));

    const response = await axios({
        method: 'post',
        url: 'http://www.yourserver.com/upload',
        data: form,
        headers: {
        'content-type': `multipart/form-data; boundary=${form._boundary}`,
        },
    });

Cette solution est également utile si vous travaillez avec React Native.


3
Cela a résolu mon problème lorsque j'essayais de publier sur l'api d'imgur. Non mentionné nulle part sur les documents, mais sans lui, vous obtenez une réponse 400 URL non valide.
Kolby

1
FormData._boundaryn'est pas défini dans Chrome 76 et Firefox 67, et axios supprime quand même l'en-tête Content-Type , cela ne devrait donc pas avoir d'effet.
Ash

1
La partie frontière était la seule chose qui manquait dans mon code, fonctionnait parfaitement dans le nœud!
Rafael Moni

vous êtes un sauveur de vie
Kevin RED

Salut, un problème bien que cela ne fonctionne que sur Android, avez-vous réussi à le faire fonctionner sur les appareils iOS?
Kevin RED

15

Télécharger (plusieurs) fichiers binaires

Node.js

Les choses se compliquent lorsque vous souhaitez publier des fichiers via multipart/form-data, en particulier plusieurs fichiers binaires. Voici un exemple de travail:

const FormData = require('form-data')
const fs = require('fs')
const path = require('path')

const formData = new FormData()
formData.append('files[]', JSON.stringify({ to: [{ phoneNumber: process.env.RINGCENTRAL_RECEIVER }] }), 'test.json')
formData.append('files[]', fs.createReadStream(path.join(__dirname, 'test.png')), 'test.png')
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData, {
  headers: formData.getHeaders()
})
  • Au lieu de headers: {'Content-Type': 'multipart/form-data' }je préfèreheaders: formData.getHeaders()
  • J'utilise asyncet awaitau - dessus, vous pouvez les changer en simples déclarations Promise si vous ne les aimez pas

Contenu nouvellement ajouté ci-dessous:

Navigateur

Le navigateur FormDataest différent du package NPM 'form-data'. Le code suivant fonctionne pour moi dans le navigateur:

HTML:

<input type="file" id="image" accept="image/png"/>

JavaScript:

const formData = new FormData()

// add a non-binary file
formData.append('files[]', new Blob(['{"hello": "world"}'], { type: 'application/json' }), 'request.json')

// add a binary file
const element = document.getElementById('image')
const file = element.files[0]
formData.append('files[]', file, file.name)
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData)

1
Merci beaucoup pour cet exemple, j'ai eu du mal à comprendre pourquoi le téléchargement de plusieurs fichiers ne fonctionnait pas.
Minkesh Jain

1
Je ne suis pas un expert, mais dans mon cas, j'ai réussi à éviter ces complications ( concat-stream, asyncet await) pour le téléchargement de fichiers multiples en utilisant for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }afin que je puisse soumettre en utilisantaxios.post(url, formData, config)
laimison

@laimison merci, ça marche pour moi. J'ai mis à jour ma réponse.
Tyler Long

@TylerLong Je ne trouve aucune méthode getHeaders dans l'API FormData. developer.mozilla.org/en-US/docs/Web/API/FormData
ankur_rajput

9

Encore plus simple:

axios.post('/addUser',{
    userName: 'Fred',
    userEmail: 'Flintstone@gmail.com'
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

2
Oui, comme il semble, s'il n'y a pas de téléchargement de fichiers, c'est le moyen le plus simple.
Akalanka Weerasooriya

3

Utilisation du format application / x-www-form-urlencoded dans axios

Par défaut, axios sérialise les objets JavaScript en JSON. Pour envoyer des données au format application / x-www-form-urlencoded à la place, vous pouvez utiliser l'une des options suivantes.

Navigateur

Dans un navigateur, vous pouvez utiliser l'API URLSearchParams comme suit:

const params = new URLSearchParams ();

params.append ('param1', 'value1');

params.append ('param2', 'value2');

axios.post ('/ foo', params);

Notez que URLSearchParams n'est pas pris en charge par tous les navigateurs (voir caniuse.com), mais un polyfill est disponible (assurez-vous de polyfill l'environnement global).

Vous pouvez également encoder des données à l'aide de la bibliothèque qs:

const qs = require ('qs');

axios.post ('/ foo', qs.stringify ({'bar': 123}));

Ou d'une autre manière (ES6),

importer qs depuis 'qs';

const data = {'bar': 123};

const options = {

méthode: 'POST',

en-têtes: {'content-type': 'application / x-www-form-urlencoded'},

données: qs.stringify (données),

url,};

axios (options);


3

2020 ES6 façon de faire

Ayant le formulaire en html, j'ai lié des données comme ceci:

LES DONNÉES:

form: {
   name: 'Joan Cap de porc',
   email: 'fake@email.com',
   phone: 2323,
   query: 'cap d\ou'
   file: null,
   legal: false
},

onSubmit:

async submitForm() {
  const formData = new FormData()
  Object.keys(this.form).forEach((key) => {
    formData.append(key, this.form[key])
  })

  try {
    await this.$axios.post('/ajax/contact/contact-us', formData)
    this.$emit('formSent')
  } catch (err) {
    this.errors.push('form_error')
  }
}

1

La méthode ci-dessus a fonctionné pour moi, mais comme c'était quelque chose dont j'avais souvent besoin, j'ai utilisé une méthode de base pour les objets plats. Remarque, j'utilisais également Vue et non REACT

packageData: (data) => {
  const form = new FormData()
  for ( const key in data ) {
    form.append(key, data[key]);
  }
  return form
}

Ce qui a fonctionné pour moi jusqu'à ce que je tombe sur des structures de données plus complexes avec des objets et des fichiers imbriqués qui ont ensuite permis aux éléments suivants

packageData: (obj, form, namespace) => {
  for(const property in obj) {
    // if form is passed in through recursion assign otherwise create new
    const formData = form || new FormData()
    let formKey

    if(obj.hasOwnProperty(property)) {
      if(namespace) {
        formKey = namespace + '[' + property + ']';
      } else {
        formKey = property;
      }

      // if the property is an object, but not a File, use recursion.
      if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
        packageData(obj[property], formData, property);
      } else {
        // if it's a string or a File
      formData.append(formKey, obj[property]);
      }
    }
  }
  return formData;
}

objectToFormData n'est pas défini et formData est renvoyé en dehors du for, mais est défini à l'intérieur du for. formData est facile, mais que doit être objectToFormData?
Trevor

Je pense que c'est censé être le nom de la fonction. parce que c'est censé être récursif, donc je suppose que vous pouvez changer le objectToFormDatapour packageDataou vice versa
Raymond Ativie

0
import axios from "axios";
import qs from "qs";   

const url = "https://yourapplicationbaseurl/api/user/authenticate";
    let data = {
      Email: "testuser@gmail.com",
      Password: "Admin@123"
    };
    let options = {
      method: "POST",
      headers: { "content-type": "application/x-www-form-urlencoded" },
      data: qs.stringify(data),
      url
    };
    axios(options)
      .then(res => {
        console.log("yeh we have", res.data);
      })
      .catch(er => {
        console.log("no data sorry ", er);
      });
  };
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.