Solicitud POST de Nodejs multipart / form-data

Estoy intentando subir una foto a través de una solicitud POST con el request module

De acuerdo con el archivo Léame, debería ser capaz de hacer esto

 var r = request.post("http://posttestserver.com/post.php", requestCallback) var form = r.form() form.append("folder_id", "0"); form.append("filename", fs.createReadStream(path.join(__dirname, "image.png"))); function requestCallback(err, res, body) { console.log(body); } 

El problema es que esto no funciona. Recibo una respuesta del servidor de prueba diciendo que descargó 0 variables de publicación.

He confirmado que el servidor está en condiciones de trabajo con esta pequeña página html

   
File:

Entonces la pregunta es, ¿qué estoy haciendo mal con el módulo de solicitud? ¿Hay una mejor manera de enviar multipart/form-data con node?

Después de investigar un poco más, decidí usar el restler module . Hace la carga multiparte realmente fácil.

 fs.stat("image.jpg", function(err, stats) { restler.post("http://posttestserver.com/post.php", { multipart: true, data: { "folder_id": "0", "filename": restler.file("image.jpg", null, stats.size, null, "image/jpg") } }).on("complete", function(data) { console.log(data); }); }); 

Así que terminé de luchar con esto yo mismo y esto es lo que aprendí:

Resulta que ni la solicitud ni los datos de formulario están configurando el encabezado de longitud de contenido para la transmisión de cuerpo generada.

Aquí está el problema informado: https://github.com/mikeal/request/issues/316

La solución publicada por @lildemon soluciona esto mediante:

  1. Generando el objeto FormData
  2. Obteniendo su longitud
  3. Realizando la solicitud y configurando explícitamente el objeto de formulario y el encabezado content-length

Aquí hay una versión modificada de tu ejemplo:

 var request = require('request'); var FormData = require('form-data'); var form = new FormData(); form.append("folder_id", "0"); form.append("filename", fs.createReadStream(path.join(__dirname, "image.png"))); form.getLength(function(err, length){ if (err) { return requestCallback(err); } var r = request.post("http://posttestserver.com/post.php", requestCallback); r._form = form; r.setHeader('content-length', length); }); function requestCallback(err, res, body) { console.log(body); } 

Tengo un código de trabajo que hace exactamente lo que dice tu pregunta, con una excepción. El contenido de mi archivo se agrega de esta manera:

 form.append('file', new Buffer(...), {contentType: 'image/jpeg', filename: 'x.jpg'}); 

Para descubrir el argumento de opciones finales, tuve que profundizar en el origen de form-data de form-data . Pero esto me da una configuración funcional. (Tal vez era lo que te estabas perdiendo, pero por supuesto eso dependerá del servidor).

Intenté también módulos de solicitud y formulario-datos y no pude cargar un archivo. Puedes usar el superagente que funciona:

http://sofes.miximages.com/forms/“) .end(function(err, res) { if (err) { console.log(err) } });

Pruebe el módulo de solicitud. Funciona como cualquier otra solicitud normal de publicación

 var jsonUpload = { }; var formData = { 'file': fs.createReadStream(fileName), 'jsonUpload': JSON.stringify(jsonUpload) }; var uploadOptions = { "url": "https://upload/url", "method": "POST", "headers": { "Authorization": "Bearer " + accessToken }, "formData": formData } var req = request(uploadOptions, function(err, resp, body) { if (err) { console.log('Error ', err); } else { console.log('upload successful', body) } });