Request: Das Hochladen von Dateien funktioniert nur mit Standard-Lesestreams

Erstellt am 28. Dez. 2016  ·  26Kommentare  ·  Quelle: request/request

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

Hilfreichster Kommentar

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

Alle 26 Kommentare

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.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

mlegenhausen picture mlegenhausen  ·  4Kommentare

lupo9557 picture lupo9557  ·  3Kommentare

Guymestef picture Guymestef  ·  3Kommentare

IgorDePaula picture IgorDePaula  ·  3Kommentare

pixarfilmz112 picture pixarfilmz112  ·  3Kommentare