Ich habe versucht, eine Datei (mit mehrteiliger POST-Anforderung) hochzuladen, die sich im TAR-Archiv befindet (ich verwende die tar-stream
-Bibliothek, um einen Stream zu einer bestimmten Datei im TAR-Archiv zu erhalten). Aber es schlägt immer mit dem ECONNRESET-Fehler fehl. Nach ein wenig Experimentieren scheint es, als ob es nur Streams hochladen kann, die direkt mit fs.createReadStream
erstellt wurden, und schlägt mit irrelevanten Fehlern für alle anderen Streams fehl.
Hier ist ein Minimalbeispiel, um das Problem zu reproduzieren. Wenn der Stream PassThrough
an formData
übergeben wird, tritt der folgende Fehler auf:
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);
Klient:
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 });
});
Ich habe das gleiche Problem, wenn ich versuche, ein Buffer
in einen Lesestrom einzuschließen, um es als gültige mehrteilige Anfrage hochzuladen.
Ich habe auch einige Zeit versucht, einen Weg zu finden, dieses Problem zu umgehen, und habe die gleichen oben genannten Probleme erlebt. Hat jemand dafür einen Workaround gefunden? Vielleicht ist dies tatsächlich ein Fehler mit dem form-data-Paket?
Dasselbe Problem hier, ich habe eine base64-Zeichenfolge und muss sie als Datei senden. Ich konvertiere mein base64 in einen Puffer und verpacke es dann, genau wie @philipp-spiess, in einen Lesestrom, aber es funktioniert nicht. Habt ihr einen Workaround gefunden?
Update: Im Moment verwendet meine Problemumgehung bhttp (https://www.npmjs.com/package/bhttp), das streams2 verwendet
Ich habe es geschafft, meine Datei direkt über den Puffer hochzuladen. Sie müssen nur dateibezogene Informationen angeben (Dateiname, Typ, ...)
var formData = {
'file': {
value: buffer,
options: {
filename: file.filename,
contentType: file.mimetype
}
}
}
https://github.com/form-data/form-data#alternative -submission-methods
@PierreCavalet , ich habe es auf diese Weise versucht, aber leider hat es nicht funktioniert.
Meine "Problemumgehung" bestand einfach darin, die Bibliothek request
nicht zu verwenden und den mehrteiligen POST mit dem http-Dienst von nodejs zu implementieren.
@PierreCavalet Ist Ihr Puffer bereits codierter Text? Für mich ist der Puffer zufällig ein binärer Blob, der die Codierung der Anfrage unterbrochen hat (da sie anscheinend nicht richtig codiert war).
Edit: Anscheinend ist keine spezielle Codierung erforderlich, vielleicht nur ein falscher Bit-Offset?! Wie auch immer, ich erinnere mich, dass der Fehler der Server war, der sich über ein ungültiges Byte beschwerte.
@philipp-spiess mein Puffer wird erstellt mit:
Buffer.from(base64string, 'base64')
Also ja, es ist ein binärer Blob. Die Dokumentation besagt, dass ein neuer Puffer erstellt wird, der die angegebene JavaScript-Zeichenfolge enthält. Falls angegeben, identifiziert der Parameter encoding die Zeichenkodierung von string.
@PierreCavalet Das von mir verwendete Buffer
stammte direkt von multer
, einer Datei-Upload-Middleware für express
.
@philipp-spiess Das ist komisch. Meine base64-Zeichenfolge stammt aus einer base64-Codierung eines Puffers, und dieser Puffer stammt direkt aus meinem Datei-Upload. (Die Verschlüsselung wird von einem anderen Dienst durchgeführt, deshalb "kodieren und dekodieren" wir für "nichts"). Sollte also auch bei dir funktionieren.
@samkelly vielen Dank für Ihre Empfehlung, bhttp zu verwenden. Es funktioniert perfekt!
@ bchr02 zB!
Habe diesen Fehler aufgespürt: Es stellt sich heraus, dass es sich um ein Problem mit der Funktion _length_retriever von form-data handelt. Wenn Sie einen Stream haben, der nicht zu den 3 vollständig verstandenen Streams gehört (im Grunde Dateien mit einem fd
-Feld, HTTP-Antworten oder Anforderungsausgabestreams), müssen Sie form-data im Grunde lügen, um ihn zum Laufen zu bringen das Richtige (und Sie müssen die genaue Bytelänge des Streams haben). Um es zum Laufen zu bringen, habe ich am Ende Folgendes getan:
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
}
}
}
Ganz wichtig: Sie MÜSSEN das Feld filename
im Feld options
angeben, sonst bekommen Sie eine weitere Ausnahme.
Wenn Sie die Dateioptionen angeben können, sollten Sie in der Lage sein, options.knownLength
mit der Bytelänge Ihres Dateistreams anzugeben, und es wird von FormData abgeholt.
Es wird in der Readme-Datei von FormData erwähnt, obwohl es nicht wirklich viel veröffentlicht wurde. Die Anfrage erwähnt es im Moment nirgendwo, soweit ich das beurteilen kann.
Ah, das hat funktioniert: Bringen Sie mir bei, um 2 Uhr morgens zu debuggen. Ich hätte schwören können, dass ich knownLength ausprobiert und eine Ausnahme bekommen habe, aber das könnte das Fehlen des Dateinamenfelds gewesen sein, das Chaos verursacht hat.
Dies funktioniert in meiner Situation nicht, da ich etwas hochlade, das Teil eines gzip-Streams ist, daher kenne ich die Länge nicht.
@ sam0x17 In der Tat wird es nicht, da, soweit ich das beurteilen kann, die Anfrage derzeit transfer-encoding: chunked
nicht unterstützt, daher Ihre Verwendung von bhttp.
Siehe auch
markieren
Ich hatte das gleiche Problem, hier ist meine Problemumgehung, indem ich direkt das http-Modul verwende.
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
Ich habe Ihre Problemumgehung verwendet, aber es scheint, dass der Stream überhaupt nicht gesendet wird. Ich verwende Multer auf der Empfängerseite, falls dies von Bedeutung ist.
@Ncifra Ich bin mir sicher, dass meine Problemumgehung funktioniert, da ich sie jeden Tag für mein aktuelles Projekt verwende.
Sie können Ihren Stream auf https://beeceptor.com/ testen ;)
Ich habe das tatsächlich folgendermaßen gelöst: https://github.com/form-data/form-data/issues/356#issue -234978025
Hier ist mein ursprüngliches Problem im Zusammenhang mit dem Problem: https://github.com/form-data/form-data/issues/409
@ BenjD90 Derzeit habe ich den Code zurückgesetzt und kann ihn nicht testen, da es sich um eine sehr verzögerte Funktion in dem Projekt handelte, an dem ich arbeite. Vielleicht hat mir etwas gefehlt, da all diese Tests zu viel Sparsed Code erzeugt hatten. Ich habe die Anfragen jedoch protokolliert, und das Form-Data-Objekt schien die Datei zu enthalten, aber Multer schien sie nicht zu erhalten, während die anderen nicht binären Daten korrekt gesendet wurden.
Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivität gab. Es wird geschlossen, wenn keine weiteren Aktivitäten stattfinden. Vielen Dank für Ihre Beiträge.
@stale Dieser Fehler ist stahl vorhanden und sollte am Tag behoben werden ^^
Ja, einverstanden, es ist heute genauso wichtig wie damals. Ich habe im Grunde darauf gewartet, dass dies behoben wird, bevor ich wieder request
anstelle von bhttp
verwende. Dies ist eine grundlegende Funktion der Streams- und Streams2-API und sollte von request
vollständig unterstützt werden.
Siehe https://github.com/form-data/form-data/pull/397#issuecomment -471976669 und https://github.com/bitinn/node-fetch/pull/707#issuecomment -569850948
Hilfreichster Kommentar
Ich habe es geschafft, meine Datei direkt über den Puffer hochzuladen. Sie müssen nur dateibezogene Informationen angeben (Dateiname, Typ, ...)
https://github.com/form-data/form-data#alternative -submission-methods