Axios wysyła żądanie wysłania danych formularza


204

POSTżądanie axios uderza w adres URL na kontrolerze, ale ustawienie wartości null dla mojej klasy POJO, kiedy przeglądam narzędzia programistyczne w chrome, ładunek zawiera dane. Co ja robię źle?

Żądanie 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);
});

Odpowiedź przeglądarki:

wprowadź opis zdjęcia tutaj

Jeśli ustawię nagłówki jako:

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

Żądanie zgłasza błąd

Błąd podczas publikowania danych wieloczęściowych / formularzy. Nagłówek Content-Type nie ma granicy

Jeśli zrobię to samo w listonoszu, działa dobrze i ustawia wartości dla mojej klasy POJO.

Czy ktoś może wyjaśnić, jak ustawić granicę lub jak wysłać dane formularza za pomocą axios.

Odpowiedzi:


329

Możesz publikować dane axios przy użyciu FormData (), takich jak:

var bodyFormData = new FormData();

A następnie dodaj pola do formularza, który chcesz wysłać:

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

Jeśli przesyłasz obrazy, możesz chcieć użyć .append

bodyFormData.append('image', imageFile); 

Następnie możesz użyć metody axios post (możesz ją odpowiednio zmienić)

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

Możesz przeczytać więcej tutaj


8
bodyFormData.set nie jest funkcją Mam ten błąd
Manoj Bhardwaj

10
Musisz użyć append zamiast set.
Pratik Singhal

1
@ManojBhardwaj musisz powiązać funkcję, przypuśćmy, że jeśli tworzysz żądanie w funkcji wysyłania, musisz powiązać tę funkcję. ex: - onSubmit = {this.submit (bind (this)} lub ex: - in konstruktor konstruktora (super) {this.submit = this.submit.bind (this);} subm () {axios ({}) ; ...}
Srikanth Gowda

bodyFormData.append też działa dla mnie. nie jestem pewien, dlaczego setnie działa
Im Batman

1
Twój obiekt konfiguracji jest nieprawidłowy. Powinno to być:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor

35

Sprawdź querystring .

Możesz użyć tego w następujący sposób:

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

4
Jest to jeszcze lepsze w środowisku węzłowym
Jjagwe Dennis

Jeśli zagnieżdżono obiekty w danych, funkcja „querystring” może nie działać zgodnie z oczekiwaniami. W takim przypadku możesz użyć modułu „qs” do zszeregowania danych.
Zihad Ul Islam

33

W moim przypadku musiałem dodać granicę do nagłówka w następujący sposób:

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

To rozwiązanie jest również przydatne, jeśli pracujesz z React Native.


3
To rozwiązało mój problem podczas próby wysłania do interfejsu API imgur. Nigdzie nie wspomniano w dokumentach, ale bez niego otrzymasz odpowiedź 400 Nieprawidłowy adres URL.
Kolby

1
FormData._boundaryjest niezdefiniowany zarówno w Chrome 76, jak i Firefox 67, a axios i tak usuwa nagłówek Content-Type , więc nie powinno to mieć żadnego efektu.
Ash

1
Część graniczna była jedyną rzeczą, której brakowało w moim kodzie, działała perfekcyjnie w węźle!
Rafael Moni

jesteś wybawcą życia
Kevin RED

Cześć, jeden problem, choć działa to tylko w Androidzie, czy udało Ci się sprawić, że działa na urządzeniach z iOS?
Kevin RED

15

Prześlij (wiele) plików binarnych

Node.js

Sprawy komplikują się, gdy chcesz publikować pliki multipart/form-data, zwłaszcza wiele plików binarnych. Poniżej znajduje się działający przykład:

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()
})
  • Zamiast tego headers: {'Content-Type': 'multipart/form-data' }wolęheaders: formData.getHeaders()
  • Używam asynci awaitpowyżej, możesz je zmienić na proste oświadczenia Obietnicy, jeśli ich nie lubisz

Nowo dodana treść poniżej:

Przeglądarka

Przeglądarka FormDataróżni się od „formularza-danych” pakietu NPM. Poniższy kod działa dla mnie w przeglądarce:

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
Dziękuję bardzo za ten przykład, z trudem zastanawiałem się, dlaczego przesyłanie wielu plików nie działa.
Minkesh Jain,

1
Nie jestem ekspertem, ale w moim przypadku udało mi się uniknąć tych komplikacji ( concat-stream, asynci await) dla wielu przesyłanie plików za pomocą for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }tak mogę przesłać używającaxios.post(url, formData, config)
laimison

@ laimison dzięki, to działa dla mnie. Zaktualizowałem swoją odpowiedź.
Tyler Long

@TylerLong Nie mogę znaleźć żadnej metody getHeaders w interfejsie API FormData. developer.mozilla.org/en-US/docs/Web/API/FormData
ankur_rajput

9

Jeszcze bardziej proste:

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

2
Tak, jak się wydaje, jeśli nie ma przesyłania plików, jest to najłatwiejszy sposób.
Akalanka Weerasooriya

3

Wykorzystanie formatu application / x-www-form-urlencoded w axios

Domyślnie axios serializuje obiekty JavaScript do JSON. Aby zamiast tego przesłać dane w formacie application / x-www-form-urlencoded, możesz użyć jednej z następujących opcji.

Przeglądarka

W przeglądarce można użyć interfejsu API URLSearchParams w następujący sposób:

const params = new URLSearchParams ();

params.append („param1”, „wartość1”);

params.append („param2”, „wartość2”);

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

Zauważ, że URLSearchParams nie jest obsługiwany przez wszystkie przeglądarki (patrz caniuse.com), ale dostępna jest funkcja wielokrotnego wypełniania (pamiętaj, aby wypełnić globalne środowisko).

Alternatywnie możesz kodować dane za pomocą biblioteki qs:

const qs = wymagany („qs”);

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

Lub w inny sposób (ES6),

import qs z „qs”;

const data = {'bar': 123};

const options = {

metoda: „POST”,

nagłówki: {'content-type': 'application / x-www-form-urlencoded'},

data: qs.stringify (dane),

url};

axios (opcje);


3

Sposób działania ES6 2020

Mając formularz w html powiązałem dane w następujący sposób:

DANE:

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

Powyższa metoda działała dla mnie, ale ponieważ była to rzecz, której często potrzebowałem, zastosowałem podstawową metodę dla płaskiego obiektu. Uwaga: używałem również Vue, a nie REACT

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

Co działało dla mnie, dopóki nie natrafiłem na bardziej złożone struktury danych z zagnieżdżonymi obiektami i plikami, które następnie pozwoliły na następujące

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 jest niezdefiniowany, a formData jest zwracany poza for, ale jest zdefiniowany wewnątrz for. FormData jest łatwa, ale czym powinna być objectToFormData?
Trevor,

Myślę, że powinna to być nazwa funkcji. bo to ma być rekurencyjne, więc zakładam, można zmienić objectToFormDatana packageDataodwrót
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);
      });
  };
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.