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: '[email protected]'
}

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.

Srikanth Gowda
la source

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

Aaqib
la source
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' }));
cclient
la source
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.

Luiz Dias
la source
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)
Tyler Long
la source
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: '[email protected]'
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});
thomasL
la source
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);

kartick shaw
la source
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: '[email protected]',
   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')
  }
}
Despertaweb
la source
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;
}
Juan Pablo Ugas
la source
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: "[email protected]",
      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);
      });
  };
ABHIJEET KHIRE
la source