Saya telah mencoba mengunggah file (menggunakan permintaan POST multi-bagian) yang ada di dalam arsip TAR (saya menggunakan perpustakaan tar-stream
untuk mendapatkan aliran ke file tertentu di dalam arsip TAR). Tapi selalu gagal dengan kesalahan ECONNRESET. Setelah sedikit bereksperimen, sepertinya itu hanya dapat mengunggah aliran yang dibuat secara langsung dengan fs.createReadStream
dan gagal dengan kesalahan yang tidak relevan untuk semua aliran lainnya.
Berikut adalah contoh minimal untuk mereproduksi masalah. Jika aliran PassThrough
dilewatkan ke formData
maka terjadi kesalahan berikut:
ERROR { Error: socket hang up
at createHangUpError (_http_client.js:254:15)
at Socket.socketOnEnd (_http_client.js:346:23)
at emitNone (events.js:91:20)
at Socket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9) code: 'ECONNRESET' }
Server:
var http = require('http');
http.createServer(function (request, response) {
request.on('data', function(chunk) {
console.log(chunk.length);
});
request.on('end', function() {
response.writeHead(200, "OK", {'Content-Type': 'text/html'});
response.end();
});
}).listen(8077);
Klien:
var request = require('request');
var fs = require('fs');
var PassThrough = require('stream').PassThrough;
var rs = fs.createReadStream('some_file.bin'), pt = new PassThrough();
rs.pipe(pt);
request({
'method': 'POST',
'url': 'http://127.0.0.1:8077',
'formData': {
'uploaded_file': pt
}
}, function (err, httpResponse, body)
{
if (err)
console.log('ERROR', err);
else
console.log({ 'statusCode': httpResponse.statusCode, 'body': body });
});
Saya mengalami masalah yang sama ketika saya mencoba untuk membungkus Buffer
dalam aliran baca untuk mengunggahnya sebagai permintaan multi-bagian yang valid.
Saya juga telah mencoba mencari cara untuk mengatasi masalah ini selama beberapa waktu dan mengalami masalah yang sama yang disebutkan di atas. Adakah yang menemukan solusi untuk ini? Mungkin ini sebenarnya bug dengan paket form-data?
Masalah yang sama di sini, saya memiliki string base64 dan saya harus mengirimkannya sebagai file. Saya mengonversi base64 saya menjadi buffer dan kemudian, seperti @philipp-spiess, saya membungkusnya dalam aliran baca, tetapi tidak berhasil. Apakah kalian menemukan pekerjaan di sekitar?
perbarui: untuk saat ini solusi saya menggunakan bhttp (https://www.npmjs.com/package/bhttp) yang menggunakan streams2
Saya telah berhasil mengunggah file saya menggunakan buffer secara langsung. Anda hanya perlu menentukan informasi terkait file (nama file, jenis, ...)
var formData = {
'file': {
value: buffer,
options: {
filename: file.filename,
contentType: file.mimetype
}
}
}
https://github.com/form-data/form-data#alternative -submission-methods
@PierreCavalet , saya mencoba cara ini tetapi sayangnya tidak berhasil.
"Solusi" saya adalah tidak menggunakan perpustakaan request
dan mengimplementasikan POST multi-bagian menggunakan layanan http nodejs.
@PierreCavalet Apakah buffer Anda sudah mengkodekan teks? Bagi saya buffer itu adalah gumpalan biner yang merusak penyandian permintaan (karena tampaknya tidak dikodekan dengan benar).
Sunting: Rupanya tidak diperlukan penyandian khusus, mungkin hanya sedikit offset yang salah ?! Bagaimanapun saya ingat bahwa kesalahannya adalah server mengeluh tentang byte yang tidak valid.
@philipp-spiess buffer saya dibuat dengan:
Buffer.from(base64string, 'base64')
Jadi ya itu adalah gumpalan biner. Dokumentasi mengatakan bahwa itu membuat Buffer baru yang berisi string JavaScript yang diberikan. Jika disediakan, parameter pengkodean mengidentifikasi pengkodean karakter string.
@PierreCavalet Buffer
yang saya gunakan langsung dari multer
, middleware pengunggahan file untuk express
.
@philipp-spiess Ini aneh. String base64 saya berasal dari penyandian base64 buffer, dan buffer ini langsung dari unggahan file saya. (Pengkodean dilakukan oleh layanan lain, itu sebabnya kami "mengkodekan dan mendekode" untuk "tidak ada"). Jadi itu harus bekerja untuk Anda juga.
@samkelly terima kasih banyak atas rekomendasi Anda untuk menggunakan bhttp . Ini bekerja dengan sempurna!
@ bchr02 misalnya!
Melacak kesalahan ini: ternyata menjadi masalah dengan fungsi _length_retriever form-data . Jika Anda memiliki aliran yang bukan salah satu dari 3 aliran yang sepenuhnya dipahami (pada dasarnya file dengan bidang fd
, respons HTTP, atau aliran keluaran permintaan), pada dasarnya Anda harus berbohong pada data formulir untuk melakukannya hal yang benar (dan Anda harus memiliki panjang byte aliran yang tepat). Untuk membuatnya berfungsi, saya akhirnya melakukan ini:
var buffer = Buffer.from(base64string, 'base64');
buffer['httpVersion'] = true;
buffer.headers = { 'content-length': 64 }
var formData = {
'file': {
value: buffer,
options: {
filename: file.filename,
contentType: file.mimetype
}
}
}
Sangat penting: Anda HARUS menentukan bidang filename
di options
, jika tidak, Anda mendapatkan pengecualian lain.
Jika Anda dapat menentukan opsi file, Anda harus dapat menentukan options.knownLength
dengan panjang byte aliran file Anda dan itu akan diambil oleh FormData.
Itu disebutkan dalam readme FormData meskipun tidak banyak dipublikasikan. Permintaan tidak menyebutkannya di mana pun sekarang sejauh yang saya tahu.
Ah, itu berhasil: ajari saya melakukan debugging apa pun pada jam 2 pagi. Saya berani bersumpah saya mencoba knownLength dan mendapat pengecualian, tapi itu mungkin karena kurangnya bidang nama file yang menyebabkan kekacauan.
ini tidak berfungsi untuk situasi saya, karena saya mengunggah sesuatu yang merupakan bagian dari aliran gzip, oleh karena itu saya tidak tahu panjangnya.
@ sam0x17 Memang tidak, sejauh yang saya tahu, permintaan saat ini tidak mendukung transfer-encoding: chunked
, jadi Anda menggunakan bhttp.
Lihat juga
tanda
Saya menghadapi masalah yang sama, inilah solusi saya, menggunakan modul http langsung.
const streamSample = fs.createReadStream('data.csv').pipe(passThrough);
const formHTTP = new FormData();
formHTTP.append('sampleFieldText', 'text-sample');
formHTTP.append('myFile', streamSample);
const requestToSend = http.request({
method: 'post',
host: 'localhost',
path: '/http',
headers: formHTTP.getHeaders()
});
formHTTP.pipe(requestToSend);
requestToSend.on('response', (res) => {
console.log('HTTP response', res.statusCode);
});
requestToSend.on('error', (e) => {
console.log('ERROR HTTP', e);
});
@BenjD90
Saya menggunakan solusi Anda, tetapi tampaknya aliran tidak terkirim sama sekali. Saya menggunakan multer di sisi penerima, jika ada relevansinya.
@Ncifra Saya yakin solusi saya berhasil, karena saya menggunakannya setiap hari di proyek saya saat ini.
Anda dapat menguji streaming Anda di https://beeceptor.com/ ;)
Saya benar-benar menyelesaikan ini dengan mengikuti: https://github.com/form-data/form-data/issues/356#issue -234978025
Ini masalah asli saya yang terkait dengan masalah: https://github.com/form-data/form-data/issues/409
@BenjD90 Saat ini saya mengembalikan kode dan tidak dapat mengujinya karena itu adalah fitur yang sangat tertunda pada proyek yang saya kerjakan. Mungkin saya melewatkan sesuatu karena semua pengujian itu telah membuat terlalu banyak kode yang jarang. Saya memang mencatat permintaan, dan objek form-data tampaknya memiliki file di dalamnya, tetapi multer tampaknya tidak menerimanya, sementara data non biner lainnya dikirim dengan benar.
Masalah ini secara otomatis ditandai sebagai basi karena tidak ada aktivitas terbaru. Ini akan ditutup jika tidak ada aktivitas lebih lanjut yang terjadi. Terima kasih atas kontribusi Anda.
@stale Bug ini ada dan harus diperbaiki pada hari itu ^^
Ya setuju, sekarang sama pentingnya dengan dulu. Saya pada dasarnya telah menunggu ini diperbaiki sebelum saya menggunakan request
lagi daripada bhttp
. Ini adalah fitur dasar dari streams dan streams2 API dan harus didukung sepenuhnya oleh request
.
Lihat https://github.com/form-data/form-data/pull/397#issuecomment -471976669 dan https://github.com/bitinn/node-fetch/pull/707#issuecomment -569850948
Komentar yang paling membantu
Saya telah berhasil mengunggah file saya menggunakan buffer secara langsung. Anda hanya perlu menentukan informasi terkait file (nama file, jenis, ...)
https://github.com/form-data/form-data#alternative -submission-methods