Axios отправить запрос на отправку данных формы


205

POSTЗапрос axios обращается к URL на контроллере, но устанавливает нулевые значения для моего класса POJO. Когда я беру инструменты разработчика в chrome, полезная нагрузка содержит данные. Что я делаю не так?

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

Ответ браузера:

введите описание изображения здесь

Если я установлю заголовки как:

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

Запрос выдает ошибку

Ошибка в публикации multipart / form-data. В заголовке Content-Type отсутствует граница

Если я делаю тот же запрос в почтальоне, он работает нормально и устанавливает значения для моего класса POJO.

Может кто-нибудь объяснить, как установить границу или как я могу отправить данные формы с помощью Axios.

Ответы:


333

Вы можете опубликовать данные axios с помощью FormData (), например:

var bodyFormData = new FormData();

А затем добавьте поля в форму, которую вы хотите отправить:

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

Если вы загружаете изображения, вы можете использовать .append

bodyFormData.append('image', imageFile); 

И тогда вы можете использовать метод сообщения Axios (вы можете изменить его соответствующим образом)

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

Вы можете прочитать больше здесь


8
bodyFormData.set не является функцией я получил эту ошибку
Манодж Bhardwaj

10
Вам нужно использовать append вместо set.
Пратик Сингхал

1
@ManojBhardwaj вам нужно связать функцию, предположим, если вы делаете запрос внутри функции отправки, вам нужно связать эту функцию. ex: - onSubmit = {this.submit (bind (this)}) или ex: - в конструкторе конструктора (супер) {this.submit = this.submit.bind (this);} submit () {axios ({}) ; ...}
Srikanth Gowda

bodyFormData.append работает для меня тоже. не уверен, почему setне работает
я Бэтмен

1
Ваш объект конфигурации неверен. Это должно быть:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Стив Тейлор

35

Проверьте строку запроса .

Вы можете использовать его следующим образом:

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

4
Это даже лучше в среде узла
Jjagwe Деннис

Если у вас есть вложенные объекты в ваших данных, строка запросов может работать не так, как ожидалось. В этом случае вы можете использовать модуль 'qs' для строкового преобразования данных.
Зихад Уль Ислам

34

В моем случае мне пришлось добавить границу к заголовку, как показано ниже:

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

Это решение также полезно, если вы работаете с React Native.


3
Это решило мою проблему при попытке опубликовать в API imgur. Не упоминается нигде на документах, но без него вы получите 400 Неверный URL-ответ.
Колби

1
FormData._boundaryне определено в Chrome 76 и Firefox 67, и axios удаляет заголовок Content-Type в любом случае , так что это не должно иметь никакого эффекта.
Пепел

1
Граница была единственной вещью, которая отсутствовала в моем коде, работала безупречно в узле!
Рафаэль Мони

ты спаситель жизни
Jithin

Привет, одна проблема, хотя это работает только в Android, вам удалось заставить его работать на устройствах iOS?
Джитин

15

Загрузить (несколько) двоичных файлов

Node.js

Ситуация усложняется, когда вы хотите разместить файлы через multipart/form-data, особенно несколько бинарных файлов. Ниже приведен рабочий пример:

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()
})
  • А headers: {'Content-Type': 'multipart/form-data' }не предпочитаюheaders: formData.getHeaders()
  • Я использую asyncи awaitвыше, вы можете изменить их на простые заявления Promise, если они вам не нравятся

Недавно добавленный контент ниже:

браузер

Браузер FormDataотличается от пакета NPM «form-data». У меня в браузере работает следующий код:

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
Огромное спасибо за этот пример, нам было трудно понять, почему не работала загрузка нескольких файлов.
Минкеш Джейн

1
Я не эксперт, но в моем случае мне удалось избежать этих осложнений ( concat-stream, asyncи await) для многократной загрузки файлов с помощью for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }так что я могу представить , используяaxios.post(url, formData, config)
laimison

@laimison спасибо, у меня все работает. Я обновил свой ответ.
Тайлер Лонг

@TylerLong Я не могу найти метод getHeaders в API FormData. developer.mozilla.org/en-US/docs/Web/API/FormData
ankur_rajput

9

Еще проще:

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

2
Да, как кажется, если нет загрузки файлов, это самый простой способ.
Акаланка Веерасория

3

Использование формата application / x-www-form-urlencoded в axios

По умолчанию axios сериализует объекты JavaScript в JSON. Чтобы вместо этого отправлять данные в формате application / x-www-form-urlencoded, вы можете использовать один из следующих вариантов.

браузер

В браузере вы можете использовать API URLSearchParams следующим образом:

const params = new URLSearchParams ();

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

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

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

Обратите внимание, что URLSearchParams поддерживается не всеми браузерами (см. Caniuse.com), но есть доступное многозаполнение (убедитесь, что оно заполнено в глобальной среде).

Кроме того, вы можете кодировать данные, используя библиотеку qs:

const qs = require ('qs');

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

Или по-другому (ES6),

импортировать qs из 'qs';

const data = {'bar': 123};

const options = {

метод: 'POST',

заголовки: {'content-type': 'application / x-www-form-urlencoded'},

данные: qs.stringify (данные),

url,};

Axios (варианты);


3

2020 ES6 способ сделать

Имея форму в HTML, я связал данные следующим образом:

ДАННЫЕ:

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

Вышеупомянутый метод работал для меня, но так как это было то, что мне часто требовалось, я использовал базовый метод для плоских объектов. Обратите внимание, я также использовал Vue, а не REACT

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

Это работало на меня, пока я не столкнулся с более сложными структурами данных с вложенными объектами и файлами, которые затем позволяют

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 не определена, а formData возвращается вне for, но определяется внутри for. С formData легко, но что такое objectToFormData?
Тревор

Я думаю, что это должно быть имя функции. потому что это означало быть рекурсивной, поэтому я предполагаю , что вы можете изменить objectToFormDataк packageDataили наоборот
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);
      });
  };
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.