axios gửi yêu cầu để gửi dữ liệu mẫu


203

POSTyêu cầu axios đang nhấn url trên bộ điều khiển nhưng đặt giá trị null cho lớp POJO của tôi, khi tôi đi qua các công cụ dành cho nhà phát triển trong chrome, tải trọng chứa dữ liệu. Tôi đang làm gì sai?

Yêu cầu POST của 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);
});

Phản hồi của trình duyệt:

nhập mô tả hình ảnh ở đây

Nếu tôi đặt tiêu đề là:

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

Yêu cầu ném lỗi

Lỗi trong việc đăng nhiều dữ liệu / biểu mẫu dữ liệu. Tiêu đề loại nội dung bị thiếu ranh giới

Nếu tôi thực hiện cùng một yêu cầu trong người đưa thư, nó sẽ hoạt động tốt và đặt các giá trị cho lớp POJO của tôi.

Bất cứ ai cũng có thể giải thích làm thế nào để thiết lập ranh giới hoặc làm thế nào tôi có thể gửi dữ liệu biểu mẫu bằng cách sử dụng axios.

Câu trả lời:


327

Bạn có thể đăng dữ liệu axios bằng cách sử dụng FormData () như:

var bodyFormData = new FormData();

Và sau đó thêm các trường vào biểu mẫu bạn muốn gửi:

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

Nếu bạn đang tải lên hình ảnh, bạn có thể muốn sử dụng .append

bodyFormData.append('image', imageFile); 

Và sau đó bạn có thể sử dụng phương pháp post axios (Bạn có thể sửa đổi nó cho phù hợp)

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

Bạn có thể đọc thêm ở đây


8
bodyFormData.set không phải là một chức năng tôi gặp lỗi này
Manoj Bhardwaj

10
Bạn cần sử dụng nối thêm thay vì thiết lập.
Pratik Singhal

1
@ManojBhardwaj bạn cần liên kết hàm, giả sử nếu bạn thực hiện yêu cầu bên trong chức năng gửi thì bạn cần liên kết chức năng đó. ex: - onSubmit = {this.submit (bind (this)} hoặc ex: - trong hàm tạo của hàm tạo (super) {this.submit = this.submit.bind (this);} submit () {axios ({}) ; ...}
Srikanth Gowda

bodyFormData.append cũng hoạt động với tôi. không chắc chắn tại sao setkhông hoạt động
Im Batman

1
Đối tượng cấu hình của bạn là sai. Nó nên là:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor

35

Kiểm tra chuỗi truy vấn .

Bạn có thể sử dụng nó như sau:

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

4
Điều này thậm chí còn tốt hơn trong môi trường nút
Jjagwe Dennis

Nếu bạn có các đối tượng lồng nhau trong dữ liệu của mình, 'chuỗi truy vấn' có thể không hoạt động như mong đợi. Trong trường hợp đó, bạn có thể sử dụng mô-đun 'qs' để xâu chuỗi dữ liệu.
Zihad Ul Hồi giáo

33

Trong trường hợp của tôi, tôi đã phải thêm ranh giới vào tiêu đề như sau:

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

Giải pháp này cũng hữu ích nếu bạn đang làm việc với React Native.


3
Điều này đã giải quyết vấn đề của tôi khi cố gắng đăng lên api của imgur. Không được đề cập ở bất cứ đâu trên các tài liệu, nhưng không có nó, bạn sẽ nhận được 400 phản hồi URL không hợp lệ.
Kolby

1
FormData._boundarykhông được xác định trong cả Chrome 76 và Firefox 67 và dù sao thì axios cũng xóa tiêu đề Kiểu nội dung , do đó, điều này sẽ không có hiệu lực.
Tro

1
Phần ranh giới là thứ duy nhất còn thiếu trong mã của tôi, hoạt động hoàn hảo trong nút!
Rafael Moni

bạn là một vị cứu tinh
Kevin RED

Xin chào, một vấn đề mặc dù điều này chỉ hoạt động trong Android mà bạn đã quản lý để làm cho nó hoạt động trên thiết bị iOS?
Kevin RED

15

Tải lên (nhiều) tệp nhị phân

Node.js

Mọi thứ trở nên phức tạp khi bạn muốn đăng các tệp qua multipart/form-data, đặc biệt là nhiều tệp nhị phân. Dưới đây là một ví dụ hoạt động:

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()
})
  • Thay vì headers: {'Content-Type': 'multipart/form-data' }tôi thíchheaders: formData.getHeaders()
  • Tôi sử dụng asyncawaitở trên, bạn có thể thay đổi chúng thành các tuyên bố Promise đơn giản nếu bạn không thích chúng

Nội dung mới được thêm vào dưới đây:

Trình duyệt

Trình duyệt FormDatakhác với gói 'dữ liệu biểu mẫu' của gói NPM. Đoạn mã sau hoạt động với tôi trong trình duyệt:

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
Cảm ơn bạn rất nhiều vì ví dụ này, đã có một thời gian khó khăn để tìm ra lý do tại sao nhiều tệp tải lên không hoạt động.
Minkesh Jain

1
Tôi không phải là một chuyên gia, nhưng trong trường hợp của tôi, tôi đã quản lý để tránh những biến chứng ( concat-stream, asyncawait) cho nhiều tải lên tập tin bằng cách sử dụng for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }để tôi có thể gửi bằngaxios.post(url, formData, config)
laimison

@laimison cảm ơn, nó làm việc cho tôi. Tôi đã cập nhật câu trả lời của mình.
Tyler Long

@TylerLong Tôi không thể tìm thấy bất kỳ phương thức getHeaders nào trong API FormData. developer.mozilla.org/en-US/docs/Web/API/FormData
ankur_rajput

9

Thậm chí đơn giản hơn:

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

2
Có, vì có vẻ như, nếu không có tệp tải lên, đây là cách dễ nhất.
Akalanka Weerasooriya

3

Sử dụng định dạng ứng dụng / x-www-form-urlencoding trong các axios

Theo mặc định, các axios tuần tự hóa các đối tượng JavaScript thành JSON. Thay vào đó, để gửi dữ liệu ở định dạng ứng dụng / x-www-form-urlencoding, bạn có thể sử dụng một trong các tùy chọn sau.

Trình duyệt

Trong trình duyệt, bạn có thể sử dụng API URLSearchParams như sau:

const params = URLSearchParams mới ();

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

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

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

Lưu ý rằng URLSearchParams không được hỗ trợ bởi tất cả các trình duyệt (xem caniuse.com), nhưng có sẵn một polyfill (đảm bảo polyfill môi trường toàn cầu).

Ngoài ra, bạn có thể mã hóa dữ liệu bằng thư viện qs:

const qs = Yêu cầu ('qs');

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

Hoặc theo một cách khác (ES6),

nhập qs từ 'qs';

const data = {'bar': 123};

tùy chọn const = {

phương thức: 'POST',

tiêu đề: {'loại nội dung': 'application / x-www-form-urlencoding'},

dữ liệu: qs.opesify (dữ liệu),

url,};

axios (tùy chọn);


3

Cách làm ES6 2020

Có dạng trong html tôi đã liên kết trong dữ liệu như vậy:

DỮ LIỆU:

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

Phương pháp trên có hiệu quả với tôi nhưng vì nó là thứ tôi cần thường xuyên, tôi đã sử dụng một phương pháp cơ bản cho vật thể phẳng. Lưu ý, tôi cũng đang sử dụng Vue và không THỰC SỰ

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

Cái này hoạt động với tôi cho đến khi tôi chạy vào các cấu trúc dữ liệu phức tạp hơn với các đối tượng và tệp được lồng vào nhau, sau đó cho phép như sau

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 không được xác định và formData được trả về bên ngoài for, nhưng được định nghĩa bên trong for. formData thì dễ, nhưng objectToFormData phải là gì?
Trevor

Tôi nghĩ rằng nó được coi là tên của chức năng. bởi vì nó có nghĩa là đệ quy, vì vậy tôi cho rằng bạn có thể thay đổi objectToFormDatathành packageDatahoặc ngược lại
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);
      });
  };
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.