axios postar solicitação para enviar dados do formulário

203

A POSTsolicitação axios está atingindo a URL no controlador, mas configurando valores nulos para minha classe POJO. Quando passo pelas ferramentas de desenvolvedor no chrome, a carga contém dados. O que estou fazendo de errado?

Solicitação POS Axios:

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

Resposta do navegador:

insira a descrição da imagem aqui

Se eu definir cabeçalhos como:

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

A solicitação lança o erro

Erro ao postar dados de várias partes / formulário. Falta o limite do cabeçalho do tipo de conteúdo

Se eu fizer o mesmo pedido no carteiro, ele está funcionando bem e define valores para minha classe POJO.

Alguém pode explicar como definir limites ou como posso enviar dados de formulário usando axios.

Srikanth Gowda
fonte

Respostas:

327

Você pode postar dados de axios usando FormData () como:

var bodyFormData = new FormData();

E adicione os campos ao formulário que você deseja enviar:

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

Se você estiver carregando imagens, poderá usar .append

bodyFormData.append('image', imageFile); 

E então você pode usar o método axios post (você pode alterá-lo de acordo)

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

Você pode ler mais aqui

Aaqib
fonte
8
bodyFormData.set não é uma função que eu tenho esse erro
Manoj Bhardwaj
10
Você precisa usar anexar em vez de definir.
precisa
1
@ManojBhardwaj, você precisa vincular a função, suponha que, se você está fazendo uma solicitação dentro da função de envio, precisa vincular essa função. ex: - onSubmit = {this.submit (bind (this)} ou ex: - no construtor construtor (super) {this.submit = this.submit.bind (this);} submit () {axios ({}) ; ...}
Srikanth Gowda
bodyFormData.append também funciona para mim. Não sei por que setnão trabalhar
Im Batman
1
Seu objeto de configuração está errado. Deve ser:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor
35

Confira a string de consulta .

Você pode usá-lo da seguinte maneira:

var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
cliente
fonte
4
Isto é ainda melhor em um ambiente de nó
Jjagwe Dennis
Se você tiver objetos aninhados em seus dados, 'querystring' pode não funcionar conforme o esperado. Nesse caso, você pode usar o módulo 'qs' para especificar os dados.
Zihad Ul Islam 22/03
33

No meu caso, tive que adicionar o limite ao cabeçalho da seguinte forma:

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

Essa solução também é útil se você estiver trabalhando com o React Native.

Luiz Dias
fonte
3
Isso resolveu meu problema ao tentar postar na API do imgur. Não mencionado em nenhum lugar nos documentos, mas sem ele você recebe uma resposta de 400 URL inválida.
quer
1
FormData._boundaryé indefinido no Chrome 76 e no Firefox 67, e axios exclui o cabeçalho Content-Type de qualquer maneira , portanto, isso não deve ter efeito.
Ash
1
A parte limite era a única coisa que faltava no meu código, funcionava perfeitamente no nó!
Rafael Moni
você é um salvador da vida
Kevin RED
Olá, um problema, embora isso funcione apenas no Android, você conseguiu fazê-lo funcionar em dispositivos iOS?
Kevin RED
15

Carregar (vários) arquivos binários

Node.js

As coisas ficam complicadas quando você deseja postar arquivos multipart/form-data, especialmente vários arquivos binários. Abaixo está um exemplo de trabalho:

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()
})
  • Em vez de headers: {'Content-Type': 'multipart/form-data' }eu prefiroheaders: formData.getHeaders()
  • Eu uso asynce awaitacima, você pode alterá-los para declarações Promise simples, se você não gosta deles

Conteúdo adicionado recentemente abaixo:

Navegador

O navegador FormDataé diferente do pacote NPM 'form-data'. O código a seguir funciona para mim no navegador:

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
fonte
1
Muito obrigado por este exemplo, tivemos dificuldade em descobrir por que o upload de vários arquivos não estava funcionando.
Minkesh Jain # 8/18
1
Eu não sou um especialista, mas no meu caso eu consegui evitar essas complicações ( concat-stream, asynce await) para upload de múltiplos arquivos usando for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }para que eu possa enviar utilizandoaxios.post(url, formData, config)
laimison
Obrigado @laimison, funciona para mim. Eu atualizei minha resposta.
Tyler Long
@TylerLong Não consigo encontrar nenhum método getHeaders na API FormData. developer.mozilla.org/pt-BR/docs/Web/API/FormData
ankur_rajput
9

Ainda mais direto:

axios.post('/addUser',{
    userName: 'Fred',
    userEmail: '[email protected]'
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});
thomasL
fonte
2
Sim, ao que parece, se não houver upload de arquivos, esta é a maneira mais fácil.
Akalanka Weerasooriya
3

Usando o formato application / x-www-form-urlencoded nos axios

Por padrão, o axios serializa objetos JavaScript em JSON. Para enviar dados no formato application / x-www-form-urlencoded, você pode usar uma das seguintes opções.

Navegador

Em um navegador, você pode usar a API URLSearchParams da seguinte maneira:

parâmetros const = novo URLSearchParams ();

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

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

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

Observe que URLSearchParams não é suportado por todos os navegadores (consulte caniuse.com), mas há um polyfill disponível (certifique-se de polyfill no ambiente global).

Como alternativa, você pode codificar dados usando a biblioteca qs:

const qs = require ('qs');

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

Ou de outra maneira (ES6),

importar qs de 'qs';

dados const = {'bar': 123};

opções const = {

método: 'POST',

cabeçalhos: {'content-type': 'application / x-www-form-urlencoded'},

data: qs.stringify (data),

url};

axios (opções);

kartick shaw
fonte
3

2020 ES6 maneira de fazer

Tendo o formulário em html, liguei os dados da seguinte forma:

DADOS:

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
fonte
1

O método acima funcionou para mim, mas como era algo que eu precisava com frequência, usei um método básico para objetos planos. Observe que eu também estava usando o Vue e não o REACT

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

O que funcionou para mim até eu encontrar estruturas de dados mais complexas com objetos e arquivos aninhados, que permitem o seguinte

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
fonte
objectToFormData é indefinido e formData é retornado fora do for, mas é definido dentro do for. formData é fácil, mas o que deve ser objectToFormData?
Trevor
Eu acho que deveria ser o nome da função. porque ele está destinado a ser recursiva, então eu suponho que você pode mudar o objectToFormDataque 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
fonte