axios โพสต์คำขอเพื่อส่งข้อมูลแบบฟอร์ม


204

POSTคำขอaxios กดปุ่ม url บนคอนโทรลเลอร์ แต่การตั้งค่า null เป็นคลาส POJO ของฉันเมื่อฉันไปถึงเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ใน chrome โครเมี่ยม payload มีข้อมูล ผมทำอะไรผิดหรือเปล่า?

คำขอ 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 ส่วนหัวของประเภทเนื้อหาไม่มีขอบเขต

ถ้าฉันทำคำขอเดียวกันกับบุรุษไปรษณีย์มันใช้งานได้ดีและตั้งค่าเป็นคลาส POJO ของฉัน

ทุกคนสามารถอธิบายวิธีตั้งค่าขอบเขตหรือฉันจะส่งข้อมูลฟอร์มโดยใช้ axios ได้ไหม

คำตอบ:


332

คุณสามารถโพสต์ข้อมูล 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 ไม่ใช่ฟังก์ชั่นฉันได้รับข้อผิดพลาดนี้
Manoj Bhardwaj

10
คุณต้องใช้ผนวกแทนการตั้งค่า
Pratik Singhal

1
@ManjBhardwaj คุณต้องผูกฟังก์ชั่นสมมติว่าถ้าคุณทำคำขอภายในฟังก์ชั่นการส่งคุณต้องผูกฟังก์ชั่นนั้น เช่น: - onSubmit = {this.submit (ผูก (นี้)) หรือ ex: - ในตัวสร้างคอนสตรัคเตอร์ (super) {this.submit = this.submit.bind (นี้);} ส่ง () {axios ({}) ; ... }
Srikanth Gowda

bodyFormData.append ก็ใช้ได้สำหรับฉันเช่นกัน ไม่แน่ใจว่าทำไมsetไม่ทำงาน
Im Batman

1
วัตถุการกำหนดค่าของคุณผิด มันควรจะเป็น:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor

35

ตรวจสอบสตริงการสืบค้น

คุณสามารถใช้มันได้ดังต่อไปนี้:

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

4
สิ่งนี้ดียิ่งขึ้นในสภาวะแวดล้อมโหนด
Jjagwe Dennis

หากคุณมีวัตถุซ้อนอยู่ในข้อมูล 'การสอบถาม' อาจไม่ทำงานอย่างที่คาดไว้ ในกรณีนั้นคุณสามารถใช้โมดูล 'qs' เพื่อทำให้ข้อมูลเป็นรูปเป็นร่าง
Zihad Ul Islam

33

ในกรณีของฉันฉันต้องเพิ่มขอบเขตไปยังส่วนหัวดังต่อไปนี้:

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 ไม่ได้กล่าวถึงที่ใดก็ตามในเอกสาร แต่ถ้าไม่มีคุณจะได้รับการตอบกลับ URL 400 ครั้งไม่ถูกต้อง
Kolby

1
FormData._boundaryไม่ได้กำหนดทั้งใน Chrome 76 และ Firefox 67 และaxios จะลบส่วนหัวของประเภทเนื้อหาต่อไปดังนั้นจึงไม่มีผลกระทบใด ๆ
Ash

1
ส่วนขอบเขตเป็นสิ่งเดียวที่หายไปจากรหัสของฉันทำงานได้ในโหนด!
Rafael Moni

คุณเป็นผู้ช่วยชีวิต
Jithin

สวัสดีมีปัญหาหนึ่งข้อแม้ว่าวิธีนี้ใช้ได้เฉพาะใน Android ที่คุณจัดการเพื่อให้ทำงานบนอุปกรณ์ iOS ได้หรือไม่
Jithin

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ข้างต้นคุณสามารถเปลี่ยนเป็นงบสัญญาธรรมดาถ้าคุณไม่ชอบพวกเขา

เนื้อหาที่เพิ่มใหม่ด้านล่าง:

เบราว์เซอร์

เบราว์เซอร์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
ขอบคุณมากสำหรับตัวอย่างนี้มีปัญหาในการหาสาเหตุที่ทำให้การอัปโหลดไฟล์หลายไฟล์ไม่ทำงาน
Minkesh Jain

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

@ ขอบคุณขอบคุณมันใช้งานได้สำหรับฉัน ฉันอัพเดตคำตอบแล้ว
Tyler Long

@TylerLong ฉันไม่พบวิธีการ getHeaders ใด ๆ ใน FormData API 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
ใช่อย่างที่คิดถ้าไม่มีไฟล์ที่อัพโหลดนี่เป็นวิธีที่ง่ายที่สุด
Akalanka Weerasooriya

3

การใช้รูปแบบแอพพลิเคชั่น / x-www-form-urlencoded เป็น axios

ตามค่าเริ่มต้น axios จะทำให้วัตถุ JavaScript เป็นอนุกรมต่อเนื่อง ในการส่งข้อมูลในรูปแบบแอพพลิเคชั่น / x-www-form-urlencoded แทนคุณสามารถใช้หนึ่งในตัวเลือกต่อไปนี้

เบราว์เซอร์

ในเบราว์เซอร์คุณสามารถใช้ URLSearchParams API ดังนี้:

const params = ใหม่ URLSearchParams ();

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

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

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

โปรดทราบว่าเบราว์เซอร์ทั้งหมดไม่สนับสนุน URLSearchParams (ดูที่ caniuse.com) แต่มีโพลีฟิลให้ใช้งาน

หรือคุณสามารถเข้ารหัสข้อมูลโดยใช้ไลบรารี qs:

const qs = ต้องการ ('qs');

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

หรืออีกวิธีหนึ่ง (ES6)

นำเข้า qs จาก 'qs';

const data = {'bar': 123};

ตัวเลือก const = {

วิธีการ: 'POST'

ส่วนหัว: {'content-type': 'application / x-www-form-urlencoded'},

data: qs.string (data)

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 ควรจะเป็นอะไร?
เทรเวอร์

ฉันคิดว่ามันควรจะเป็นชื่อของฟังก์ชั่น เพราะมันหมายถึงการเป็น recursive ดังนั้นฉันคิดว่าคุณสามารถเปลี่ยนobjectToFormDataไปpackageDataหรือในทางกลับกัน
เรย์มอนด์ 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);
      });
  };
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.