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.