axios invia una richiesta per inviare i dati del modulo


204

axios POSTrequest sta colpendo l'URL sul controller ma impostando valori null sulla mia classe POJO, quando passo attraverso gli strumenti di sviluppo in Chrome, il payload contiene dati. Che cosa sto facendo di sbagliato?

Richiesta POST Axios:

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);
});

Risposta del browser:

inserisci qui la descrizione dell'immagine

Se imposto le intestazioni come:

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

La richiesta genera l'errore

Errore durante la pubblicazione di dati multipart / form. Nell'intestazione Content-Type manca il limite

Se faccio la stessa richiesta nel postino, funziona bene e imposta i valori sulla mia classe POJO.

Qualcuno può spiegare come impostare il confine o come posso inviare i dati del modulo utilizzando axios.

Risposte:


332

Puoi pubblicare dati axios usando FormData () come:

var bodyFormData = new FormData();

Quindi aggiungi i campi al modulo che desideri inviare:

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

Se stai caricando immagini, potresti voler usare .append

bodyFormData.append('image', imageFile); 

E poi puoi usare il metodo axios post (Puoi modificarlo di conseguenza)

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);
    });

Puoi leggere di più qui


8
bodyFormData.set non è una funzione che ho ricevuto questo errore
Manoj Bhardwaj

10
Devi usare append invece di set.
Pratik Singhal,

1
@ManojBhardwaj devi associare la funzione, supponi che se stai facendo una richiesta all'interno della funzione di invio devi associare quella funzione. es: - onSubmit = {this.submit (bind (this)} o ex: - nel costruttore del costruttore (super) {this.submit = this.submit.bind (this);} submit () {axios ({}) ; ...}
Srikanth Gowda,

bodyFormData.append funziona anche per me. non so perché setnon funziona
Sono Batman il

1
Il tuo oggetto di configurazione è sbagliato. Dovrebbe essere:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor,

35

Dai un'occhiata a querystring .

Puoi usarlo come segue:

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

4
Questo è ancora meglio in un ambiente di nodi
Jjagwe Dennis,

Se hai oggetti nidificati nei tuoi dati, 'querystring' potrebbe non funzionare come previsto. In tal caso, è possibile utilizzare il modulo 'qs' per stringere i dati.
Zihad Ul Islam,

33

Nel mio caso ho dovuto aggiungere il confine al di intestazione come la seguente:

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}`,
        },
    });

Questa soluzione è utile anche se stai lavorando con React Native.


3
Questo ha risolto il mio problema quando cercavo di postare l'API di imgur. Non menzionato da nessuna parte nei documenti, ma senza di esso otterrai una risposta URL 400 non valida.
Kolby,

1
FormData._boundarynon è definito in Chrome 76 e Firefox 67 e axios elimina comunque l'intestazione Content-Type , quindi ciò non dovrebbe avere alcun effetto.
Ash,

1
La parte di confine era l'unica cosa che mancava nel mio codice, funzionava perfettamente nel nodo!
Rafael Moni,

sei un salvatore di vita
Jithin il

Ciao, un problema anche se funziona solo su Android sei riuscito a farlo funzionare su dispositivi iOS?
Jithin

15

Carica (più) file binari

Node.js

Le cose diventano complicate quando si desidera pubblicare file tramite multipart/form-data, in particolare più file binari. Di seguito è riportato un esempio funzionante:

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()
})
  • Invece di headers: {'Content-Type': 'multipart/form-data' }preferiscoheaders: formData.getHeaders()
  • Io uso asynce awaitsoprattutto, puoi cambiarle in semplici dichiarazioni Promise se non ti piacciono

Contenuto appena aggiunto di seguito:

Browser

Il browser FormDataè diverso dai "form-data" del pacchetto NPM. Il seguente codice funziona per me nel browser:

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
Grazie mille per questo esempio, è stato difficile capire perché il caricamento di più file non funzionasse.
Minkesh Jain,

1
Io non sono un esperto, ma nel mio caso sono riuscito a evitare queste complicazioni ( concat-stream, asynce await) per caricamento di più file utilizzando for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }in modo da poter presentare utilizzandoaxios.post(url, formData, config)
laimison

@laimison grazie, funziona per me. Ho aggiornato la mia risposta.
Tyler Long,

@TylerLong Non riesco a trovare alcun metodo getHeaders nell'API FormData. developer.mozilla.org/en-US/docs/Web/API/FormData
ankur_rajput

9

Ancora più semplice:

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

2
Sì, a quanto pare, se non ci sono caricamenti di file, questo è il modo più semplice.
Akalanka Weerasooriya,

3

Utilizzo del formato application / x-www-form-urlencoded in axios

Per impostazione predefinita, axios serializza gli oggetti JavaScript su JSON. Per inviare invece i dati nel formato application / x-www-form-urlencoded, puoi usare una delle seguenti opzioni.

Browser

In un browser, è possibile utilizzare l'API URLSearchParams come segue:

const params = new URLSearchParams ();

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

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

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

Tieni presente che URLSearchParams non è supportato da tutti i browser (vedi caniuse.com), ma è disponibile un polyfill (assicurati di effettuare il polyfill dell'ambiente globale).

In alternativa, puoi codificare i dati usando la libreria qs:

const qs = request ('qs');

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

O in un altro modo (ES6),

importa qs da 'qs';

const data = {'bar': 123};

const const = {

metodo: 'POST',

headers: {'content-type': 'application / x-www-form-urlencoded'},

dati: qs.stringify (dati),

url,};

Axios (opzioni);


3

2020 ES6 modo di fare

Avendo il modulo in HTML ho associato i dati in questo modo:

DATI:

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

Il metodo sopra ha funzionato per me, ma poiché era qualcosa di cui avevo bisogno spesso, ho usato un metodo di base per un oggetto piatto. Nota, stavo anche usando Vue e non REACT

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

Il che ha funzionato per me fino a quando mi sono imbattuto in strutture di dati più complesse con oggetti e file nidificati che poi hanno permesso di seguire

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 non è definito e formData viene restituito all'esterno di for, ma è definito all'interno di for. formData è semplice, ma cosa dovrebbe essere objectToFormData?
Trevor,

Penso che dovrebbe essere il nome della funzione. perché è pensata per essere ricorsiva, quindi presumo che tu possa cambiare objectToFormDatain packageDatao viceversa
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);
      });
  };
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.