Request: La carga de archivos solo funciona con secuencias de lectura estándar

Creado en 28 dic. 2016  ·  26Comentarios  ·  Fuente: request/request

He estado tratando de cargar un archivo (usando una solicitud POST de varias partes) que está dentro del archivo TAR (utilizo la biblioteca tar-stream para obtener la transmisión a un archivo en particular dentro del archivo TAR). Pero siempre falla con el error ECONNRESET. Después de experimentar un poco, parece que solo puede cargar secuencias construidas directamente con fs.createReadStream y falla con un error irrelevante para todas las demás secuencias.

Aquí hay un ejemplo mínimo para reproducir el problema. Si el flujo PassThrough se pasa a formData , se produce el siguiente error:

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' }

Servidor:

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

Cliente:

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

Comentario más útil

Logré cargar mi archivo usando el búfer directamente. Solo necesita especificar información relacionada con el archivo (nombre de archivo, tipo, ...)

var formData = {
  'file': {
    value: buffer,
    options: {
      filename: file.filename,
      contentType: file.mimetype
    }
  }
}

https://github.com/form-data/form-data#alternative-submission-methods

Todos 26 comentarios

Experimento el mismo problema cuando trato de envolver un Buffer en un flujo de lectura para cargarlo como una solicitud multiparte válida.

También he estado tratando de encontrar una forma de solucionar este problema durante algún tiempo y he experimentado los mismos problemas mencionados anteriormente. ¿Alguien ha encontrado una solución para esto? ¿Quizás esto es realmente un error con el paquete de datos de formulario?

El mismo problema aquí, tengo una cadena base64 y necesito enviarla como un archivo. Convierto mi base64 en un búfer y luego, al igual que @ philipp-spiess, lo envuelvo en un flujo de lectura, pero no funciona. ¿Ustedes encontraron un trabajo alrededor?

actualización: por ahora, mi solución es usar bhttp (https://www.npmjs.com/package/bhttp) que usa streams2

Logré cargar mi archivo usando el búfer directamente. Solo necesita especificar información relacionada con el archivo (nombre de archivo, tipo, ...)

var formData = {
  'file': {
    value: buffer,
    options: {
      filename: file.filename,
      contentType: file.mimetype
    }
  }
}

https://github.com/form-data/form-data#alternative-submission-methods

@PierreCavalet , lo intenté de esta manera pero desafortunadamente no funcionó.

Mi "solución alternativa" fue simplemente no usar la biblioteca request e implementar POST de varias partes usando el servicio http de nodejs.

@PierreCavalet ¿Su búfer ya tiene texto codificado? Para mí, el búfer resulta ser un blob binario que rompió la codificación de la solicitud (ya que aparentemente no estaba codificado correctamente).

Editar: Aparentemente, no se necesita una codificación especial, ¿tal vez solo un bit de compensación incorrecto? De todos modos, recuerdo que el error fue que el servidor se quejó de un byte no válido.

@philipp-spiess mi búfer se crea con:

Buffer.from(base64string, 'base64')

Así que sí, es un blob binario. La documentación dice que crea un nuevo búfer que contiene la cadena JavaScript dada. Si se proporciona, el parámetro de codificación identifica la codificación de caracteres de la cadena.

@PierreCavalet El Buffer que estaba usando era directamente de multer , un middleware de carga de archivos para express .

@philipp-spiess Esto es raro. Mi cadena base64 proviene de una codificación base64 de un búfer, y este búfer proviene directamente de la carga de mi archivo. (La codificación la realiza otro servicio, por eso "codificamos y decodificamos" para "nada"). Así que debería funcionar para usted también.

@samkelly muchas gracias por su recomendación de usar bhttp . ¡Funciona perfectamente!

@ bchr02 por ejemplo!

Se rastreó este error: resulta ser un problema con la función _length_retriever de form-data . Si tiene un flujo que no es uno de los 3 flujos completamente entendidos (básicamente archivos con un campo fd , respuestas HTTP o flujos de salida de solicitud), básicamente tiene que mentirle a los datos de formulario para que funcione. lo correcto (y necesita tener la longitud de bytes precisa de la transmisión). Para que funcione, terminé haciendo esto:

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

Muy importante: DEBE especificar el campo filename en options , de lo contrario obtendrá otra excepción.

Si puede especificar las opciones de archivo, debería poder especificar options.knownLength con la longitud de bytes de su flujo de archivo y FormData lo recogerá.

Se menciona en el archivo Léame de FormData, aunque en realidad no se publicita mucho. La solicitud no lo menciona en ninguna parte en este momento hasta ahora que puedo decir.

Ah, eso funcionó: enséñame a hacer cualquier depuración a las 2 am. Podría haber jurado que probé la longitud conocida y obtuve una excepción, pero eso puede haber sido la falta del campo de nombre de archivo que causó el caos.

esto no funciona para mi situación, porque estoy cargando algo que es parte de un flujo de gzip, por lo tanto, no sé la longitud.

@ sam0x17 De hecho, no lo hará, hasta donde puedo decir, la solicitud actualmente no es compatible transfer-encoding: chunked , por lo tanto, su uso de bhttp.

Ver también

Marcos

Enfrenté el mismo problema, aquí está mi solución alternativa, usando directamente el módulo http.

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
Utilicé su solución alternativa, pero parece que la transmisión no se envía en absoluto. Estoy usando multer en el extremo receptor, si tiene alguna relevancia.

@Ncifra Estoy seguro de que mi solución funciona, porque la uso todos los días en mi proyecto actual.
Puedes probar tu transmisión en https://beeceptor.com/ ;)

De hecho, resolví esto siguiendo: https://github.com/form-data/form-data/issues/356#issue -234978025
Aquí está mi problema original relacionado con el problema: https://github.com/form-data/form-data/issues/409

@ BenjD90 Actualmente revertí el código y no puedo probarlo porque era una característica muy retrasada en el proyecto en el que estoy trabajando. Tal vez me faltaba algo ya que todas esas pruebas habían creado demasiado código disperso. Sin embargo, registré las solicitudes y el objeto de datos de formulario parecía tener el archivo, pero Multer no parecía recibirlo, mientras que los otros datos no binarios se enviaban correctamente.

Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias por sus aportaciones.

@stale Este error está presente en el acero y debe corregirse el día ^^

Sí, de acuerdo, es tan importante ahora como lo era entonces. Básicamente, he estado esperando que esto se solucione antes de usar request nuevamente en lugar de bhttp . Esta es una característica básica de la API streams y streams2 y debe ser totalmente compatible con request .

¿Fue útil esta página
0 / 5 - 0 calificaciones