Axios: Permintaan POST berfungsi di Browser tetapi tidak di Node

Dibuat pada 20 Jul 2017  ·  26Komentar  ·  Sumber: axios/axios

Mirip dengan #318 , saya tidak dapat membuat permintaan posting dengan axios di node.js. Tetapi di browser potongan kode yang sama tampaknya berfungsi dengan baik.

const fdata = new FormData();
fdata.append('user', u);
fdata.append('hostnames', n.join(' '));
const host = localStorage.getItem('host');
const port = localStorage.getItem('port');
axios({
  url: `http://${host}:${port}/hosts/remove`,
  method: 'post',
  data: fdata
}).then(response => {
  if (response.status === 200) {
    console.log(response.data);
    console.log('Removed host successfully');
  }
  return null;
}).catch(er => console.log(er));

Dengan unrest berfungsi:

unirest.post(`http://${host}:${port}/hosts/remove`)
.headers({ 'Content-Type': 'multipart/form-data' })
.field('user', u)
.field('hostnames', h.join(' '))
.end(response => {
  console.log(response.body);
});
  • versi aksio :
  • Lingkungan: simpul v8.0.0, windows 8.1

Komentar yang paling membantu

Ini mungkin dianggap sebagai duplikat #789.

Saya dapat menggunakan paket form-data dengan Axios di nodejs. Ini pada dasarnya menyediakan FormData -seperti antarmuka. Namun, Anda harus berhati-hati untuk meneruskan header yang dihasilkannya ke Axios secara manual. Sebagai contoh:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result…
  console.log(result.data);
});

Semua 26 komentar

Ini mungkin dianggap sebagai duplikat #789.

Saya dapat menggunakan paket form-data dengan Axios di nodejs. Ini pada dasarnya menyediakan FormData -seperti antarmuka. Namun, Anda harus berhati-hati untuk meneruskan header yang dihasilkannya ke Axios secara manual. Sebagai contoh:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result…
  console.log(result.data);
});

Ya, saya mencoba dengan paket form-data . Yah, tidak apa-apa sekarang, saya mengubah API sisi server untuk mengurai JSON sebagai gantinya.

dapatkah seseorang tolong tunjukkan apa yang harus dilakukan di aplikasi nodejs ??

@ ar412 Saya mencoba memberikan contoh di https://github.com/mzabriskie/axios/issues/1006#issuecomment -320165427, dapatkah Anda mengklarifikasi apa yang Anda tanyakan?

@binki jika axios sedang digunakan untuk mengirim permintaan posting di restapi dengan beberapa data, lalu bagaimana cara mengambil data itu di sisa api (yang ada di dalam aplikasi ekspres).

Anda dapat mencoba ini https://expressjs.com/en/4x/api.html#req @ar412

@ar412 Untuk menerima data multi bagian di Express, Anda dapat menggunakan sesuatu seperti busboy seperti yang direkomendasikan oleh body-parser 's docs . Pada dasarnya, untuk mempelajari cara menangani file yang diunggah di Express, itu sama sekali tidak terkait dengan Axios, jadi Anda lebih baik bertanya di tempat lain karena Anda telah membajak utas ini ;-). Misalnya, lihat jawaban ini di SO .

Mendapat pesan kesalahan: form.getHeaders() bukan fungsi

@binki
Hai! Saya memiliki server hapi.js di mana saya ingin POST file gambar yang disimpan dalam variabel dengan menggunakan fs.readFile(path).
Saya tidak dapat membuatnya berfungsi dengan mengirimkannya sebagai FormData()

Ini kode saya:

fs.readFile(__dirname+'/../static/lisa_server.jpg', (error, imageData) => {
          var form = new FormData()

            form.append('file', imageData,  {
            filename: 'unicycle.jpg', // ... or:
            filepath: '/../static/lisa_server.jpg',
            contentType: 'image/jpg',
            knownLength: 19806
          })

Kemudian saya mengirim formulir sebagai badan permintaan dan saya menetapkan opsi['Content-Type'] = 'multipart/form-data'

Bisakah Anda membantu?
Sangat dihargai!

@bstolarz jika Anda melewati Buffer , yang Anda lakukan, Anda tidak perlu melewati knownLength . Juga, jika Anda membaca apa yang Anda tulis (err, menyalin dan menempel dari contoh README form-data ), Anda hanya boleh memberikan salah satu dari filename atau filepath —bukan keduanya. Satu-satunya hal yang mungkin masuk akal untuk Anda atur adalah:

  1. filename ATAU filepath
  2. contentType (jika server memerlukan nilai Tipe Konten tertentu, jika tidak, mungkin dapat dihilangkan).

Saya yakin yang terjadi adalah ukuran gambar yang Anda kirim memiliki ukuran yang bukan 19806 karena nilai 19806 adalah sesuatu yang Anda salin dari contoh di form-data 's docs daripada dihitung untuk data Anda sendiri. Ini mungkin menyebabkan form-data membuat kesalahan itu sendiri atau menulis data yang tidak valid dalam permintaan HTTP. Apakah Anda memeriksa apakah axios.post() dikembalikan Promise ditolak atau jika pengecualian dilemparkan? Jika permintaan axios ditolak, periksa apakah objek kesalahan memiliki kunci result dan, jika ya, periksa nilai err.result.status . Jika itu adalah nilai 4xx selain 404 atau 403, itu mungkin berarti server menolak permintaan yang salah format yang dapat diakibatkan oleh ukuran yang diketahui salah.

@binki
Hei, terima kasih atas tanggapan Anda. Saya mengoreksi hal-hal yang Anda sebutkan, jadi sekarang kode saya adalah

fs.readFile(__dirname+'/../static/lisa_server.jpg', (error, imageData) => {
          var form = new FormData()

          form.append('file', imageData, {
               filepath: __dirname+'/../static/lisa_server.jpg',
               contentType: 'image/jpg'

          })

Tetapi server menampilkan 411 "Panjang diperlukan" (Saya juga mencoba fs.createReadStream yang tampaknya didukung penuh oleh FormData, tetapi saya mendapatkan kesalahan panjang yang sama).

@binki
Saya berhasil mengatur panjang konten header di lapisan terendah dan saya tidak mendapatkan kesalahan itu lagi.
Sekarang saya tidak mendapatkan 411 dari server, saya kembali ke kesalahan yang pernah saya alami 400- "Tidak Ada File yang Disediakan".

Seperti inilah tampilan permintaannya

Mulai Permintaan

{ adapter: [Function: httpAdapter],
  transformRequest: { '0': [Function: transformRequest] },
  transformResponse: { '0': [Function: transformResponse] },
  timeout: 5000,
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
  maxContentLength: -1,
  validateStatus: [Function: validateStatus],
  headers:
   { common: { Accept: 'application/json, text/plain, */*' },
     delete: {},
     get: {},
     head: {},
     post: { 'Content-Type': 'application/json' },
     put: { 'Content-Type': 'application/json' },
     patch: { 'Content-Type': 'application/json' },
     'User-Agent': 'trojan server 1.0',
     'X-Origin-Panamera': 'Staging',
     'Content-Length': 25247 },
  baseURL: 'https://letgoar-a.akamaihd.net/api/v1',
  method: 'post',
  url: 'https://<baseDomain>/api/v1/images',
  data:
   FormData {
     _overheadLength: 218,
     _valueLength: 25247,
     _valuesToMeasure: [],
     writable: false,
     readable: true,
     dataSize: 0,
     maxDataSize: 2097152,
     pauseStreams: true,
     _released: false,
     _streams:
      [ '----------------------------677738213014296377492349\r\nContent-Disposition: form-data; name="file"; filename="/Users/brenda/repos/qreator2/qreator/trojan-server/src/static/lisa_server.jpg"\r\nContent-Type: image/jpg\r\n\r\n',
        <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e2 11 2c 49 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 11 1c 61 70 70 6c 02 00 00 00 ... >,
        [Function: bound ] ],
     _currentStream: null,
     _boundary: '--------------------------677738213014296377492349' },
  'Content-Type': 'multipart/form-data' }

Harap Anda memeriksa ini. Bagi Anda, apakah ini terlihat seperti permintaan yang masuk akal?

Terima kasih sebelumnya

@bstolarz Saya telah melakukan yang terbaik untuk mereproduksi masalah Anda. Namun, saya tidak bisa. Saya menulis kode ini untuk mencoba meniru apa yang Anda lakukan. Namun, saya sengaja menghilangkan pengaturan manual Content-Length . Saya yakin bahwa fakta bahwa Anda menyetel Content-Length mungkin terkait dengan masalah Anda. Silakan coba biarkan form-data mengurus perhitungan itu untuk Anda—itu sebabnya Anda harus menelepon form.getHeaders() .

Lihat tempel ini: https://Gist.github.com/binki/10ac3e91851b524546f8279733cdadad . Mungkin Anda dapat mengubah cara Anda memanggil axios.post() atau axios() agar sesuai dengan contoh saya dan itu akan berhasil untuk Anda?

Jika Anda masih mengalami masalah, coba pindahkan kode Anda ke skripnya sendiri dan buat ulang di sana. Ini dapat membantu Anda untuk memecahkan masalah. Jika Anda masih buntu, silakan posting kode lengkap, termasuk panggilan ke axios() atau axios.post() sebagai inti dan tautkan di sini dan, jika saya bisa, saya akan memeriksanya.

Itu masih tidak berfungsi sama sekali ...

@rodrigogs Jika Anda ingin bantuan, Anda harus lebih detail ;-).

Saya mengikuti penelitian bermanfaat ini tentang Axios dan solusi terakhir berfungsi untuk saya ( tautan )

Ini copy/paste nya :

import fs from 'fs';
import FormData from 'form-data';
import axios from 'axios';

let data = fs.createReadStream(__dirname + '/test.jpg');
let form = new FormData();

form.append('type','image');
form.append('media',data,'test.jpg');

function getHeaders(form) {
    return Promise((resolve, reject) => {
        form.getLength((err, length) => {
            if(err) { reject(err); }
            let headers = Object.assign({'Content-Length': length}, form.getHeaders());
            resolve(headers);
         });
    });
}

getHeaders(form)
.then((headers) => {
    return axios.post(url, form, {headers:headers})
})
.then((response)=>{
    console.log(response.data)
})
.catch(e=>{console.log(e)})

@westofpluto , saya juga mendapatkan kesalahan yang sama. @binki , ada pemikiran?
kesalahan
form.getHeaders bukan fungsi

@smplyjr Bisakah Anda memberikan lebih banyak konteks dan beri tahu saya bagaimana Anda mendapatkan form ? Tanpa kode, kami tidak dapat mengetahui apa yang Anda lakukan atau membantu Anda.

Untuk pengguna nodejs selesaikan dengan menggunakan lib querystring, sebagai berikut:

const querystring = require('querystring')
axios
  .post(URL, querystring.stringify(data))
  .then((response) => ...)
  .catch((error) => ...)

Seperti yang disebutkan @heldrida , gunakan querystring. Itulah cara axios merekomendasikan melakukannya juga di sini: https://www.npmjs.com/package/axios#nodejs. Paket form-data memiliki segala macam masalah di sini dan Anda hanya akan menarik rambut Anda mencoba membuatnya bekerja.

@heldrida @ashok-sc Bagaimana saya perlu menggunakan querystring atau qs untuk mengupload file dengan axios? Saya menggunakan aksioma untuk mengunggah file dari AWS Lambda dan saya jelas tidak memiliki akses ke objek File dari sana

@bstolarz Saya telah melakukan yang terbaik untuk mereproduksi masalah Anda. Namun, saya tidak bisa. Saya menulis kode ini untuk mencoba meniru apa yang Anda lakukan. Namun, saya sengaja menghilangkan pengaturan manual Content-Length . Saya yakin bahwa fakta bahwa Anda menyetel Content-Length mungkin terkait dengan masalah Anda. Silakan coba biarkan form-data mengurus perhitungan itu untuk Anda—itu sebabnya Anda harus menelepon form.getHeaders() .

Lihat tempel ini: https://Gist.github.com/binki/10ac3e91851b524546f8279733cdadad . Mungkin Anda dapat mengubah cara Anda memanggil axios.post() atau axios() agar sesuai dengan contoh saya dan itu akan berhasil untuk Anda?

Jika Anda masih mengalami masalah, coba pindahkan kode Anda ke skripnya sendiri dan buat ulang di sana. Ini dapat membantu Anda untuk memecahkan masalah. Jika Anda masih buntu, silakan posting kode lengkap, termasuk panggilan ke axios() atau axios.post() sebagai inti dan tautkan di sini dan, jika saya bisa, saya akan memeriksanya.

Terima kasih sobat. Menambahkan Content-Length memecahkan masalah saya sekarang saya dapat menggunakan panggilan backend-2-backend axios dengan FormData:
const options = { method: 'POST', url: myUrl, data: justJsonBody, transformRequest: [function (data, headers) { const formData = convertToFormData(data); // returrns ForrmData from form-data headers['Content-Type'] = formData.getHeaders()['content-type']; headers['Content-Length'] = formData._overheadLength; return formData; }] };

Ini mungkin dianggap sebagai duplikat #789.

Saya dapat menggunakan paket form-data dengan Axios di nodejs. Ini pada dasarnya menyediakan FormData -seperti antarmuka. Namun, Anda harus berhati-hati untuk meneruskan header yang dihasilkannya ke Axios secara manual. Sebagai contoh:

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
  headers: form.getHeaders(),
}).then(result => {
  // Handle result…
  console.log(result.data);
});

Cara lain di sini. Dengan cara ini, Anda dapat menambahkan agen proxy ke dan konfigurasi lainnya:

const axios = require('axios');
const FormData = require('form-data');
const ProxyAgent = require('proxy-agent');

const form = new FormData();
// Second argument  can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios({
  method: 'POST',
  url: 'http://example.org/endpoint',
  data: form,
  agent: new ProxyAgent("https://username:[email protected]:8080"),
  headers: bodyFormData.getHeaders()
}).then(result => {
  // Handle result…
  console.log(result.data);
});

Ini bekerja untuk saya.

// ES6
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';

FormData.prototype.getHeadersWithContentLength = function getHeadersWithContentLength() {
  return new Promise((resolve, reject) => {
    this.getLength((err, length) =>
      err ? reject(err) : resolve({ ...this.getHeaders(), 'Content-Length': length })
    )
  })
}

const payload = new FormData();
const form = new formidable.IncomingForm();

form.parse(req, (err, fields, { file }) => {
  if (err) return;

  payload.append("file", fs.createReadStream(file.path), {
    filename: file.name,
    contentType: file.type
  });

  payload.getHeadersWithContentLength().then(headers => {
    api
      .post(endpoint, payload, { headers })
      .then(({ data }) => data)
      .then(data => res.json({ data }));
  });
});

Terima kasih kepada semua kontributor posting ini. Setelah menghabiskan berjam-jam mengalami masalah POSTing formulir form-data menggunakan Axios, ke backend yang mempostingnya ke ember Amazon, solusinya ternyata mengatur content-length secara manual ....

Bagi siapa pun yang mengalami masalah dengan kode saya, mungkin ini dapat membantu baris berikutnya yang mengalami masalah agar ini berfungsi :)

const axios = require('axios');
const FormData = require('form-data');

// Where buffer is a file
formData.append('file', buffer);

// Added a promise version like seen in earlier comments to get this
const contentLength = await formData.getLength();

await axios(`<ENDPOINT>`, {
    method: 'POST',
    baseURL: <BASE_URL>,
    params: {
        fileName: '<FILE_NAME>.png'
    },
    headers: {
        authorization: `Bearer <TOKEN>`,
        ...formData.getHeaders(),
        'content-length': contentLength
    },
    data: formData
});

Setelah menghabiskan berjam-jam mengalami masalah POSTing formulir form-data menggunakan Axios, ke backend yang mempostingnya ke ember Amazon, solusinya ternyata mengatur content-length secara manual ....

Ya. Saya dan seorang rekan saya juga menghabiskan beberapa jam ketika mencoba POST file ke backend yang akan menjawab bahwa tidak ada data yang dikirimkan, padahal jelas, karena kami dapat melacak permintaan dan melihat kontennya. Masalahnya adalah header panjang konten yang hilang.

Sebagai catatan, jika Anda menambahkan buffer ke FormData, tidak apa-apa jika Anda memanggil formData.getLengthSync() tetapi jika Anda berurusan dengan aliran, Anda harus terlebih dahulu membuat stat file dengan fs.statSync(filePath).size atau dapatkan ukuran penuh dengan cara lain (seperti dari header panjang konten dari hulu), misalnya jika aliran berasal dari permintaan atau soket atau apa pun. Jika aliran Anda berasal dari disk, fs.statSync(filePath).size akan memberikan ukuran dalam byte, sehingga Anda dapat menambahkannya dalam panjang yang diketahui saat menambahkan ke FormData:

formData.append("file", fs.createReadStream(filePath), { filename: 'whatever.pdf', knownLength: fs.statSync(filePath).size });

Tentu saja semua metode Sinkronisasi dapat dialihkan untuk metode asinkron dan kata kunci menunggu.

// Added a promise version like seen in earlier comments to get this
const contentLength = formData.getLength();

Saya kira Anda lupa await sebelum formData memang...

Apakah halaman ini membantu?
0 / 5 - 0 peringkat