web-dev-qa-db-fra.com

Nodejs POST demande multipart / form-data

J'essaie de télécharger une photo via une demande POST avec la request module

Selon le fichier lisez-moi, je devrais simplement pouvoir le faire

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

Le problème est que cela ne fonctionne pas. Je reçois une réponse du serveur de test disant qu'il a vidé 0 variables de publication.

J'ai confirmé que le serveur est en état de marche avec cette petite page html

<html>
    <body>
        <form action="http://posttestserver.com/post.php?dir=example" method="post" enctype="multipart/form-data">
            File: <input type="file" name="submitted">
            <input type="hidden" name="someParam" value="someValue"/>
            <input type="submit" value="send">
        </form>
    </body>
</html>

La question est donc: qu'est-ce que je fais mal avec le module de demande? Existe-t-il une meilleure façon d'envoyer multipart/form-data avec noeud?

30
giodamelio

Après quelques recherches supplémentaires, j'ai décidé d'utiliser le restler module . Cela facilite le téléchargement en plusieurs parties.

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

Je viens donc de finir de lutter avec ça moi-même et voici ce que j'ai appris:

Il s'avère qu'aucune requête ou donnée de formulaire ne définit l'en-tête de longueur de contenu pour le flux de corps généré.

Voici le problème signalé: https://github.com/mikeal/request/issues/316

La solution publiée par @ lildemon contourne ce problème en:

  1. Génération de l'objet FormData
  2. Obtenir sa longueur
  3. Faire la demande et définir explicitement l'objet de formulaire et l'en-tête de longueur de contenu

Voici une version modifiée de votre exemple:

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

J'ai un code de travail qui fait exactement ce que dit votre question, à une exception près. Le contenu de mon fichier est ajouté de cette façon:

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

Pour découvrir l'argument des options finales, j'ai dû explorer la source de form-data. Mais cela me donne une configuration de travail. (Peut-être que c'était ce qui vous manquait, mais bien sûr cela dépendra du serveur.)

4
wberry

J'ai également essayé les modules de demande et de données de formulaire et je n'ai pas pu télécharger de fichier. Vous pouvez utiliser un superagent qui fonctionne:

http://visionmedia.github.io/superagent/#multipart-requests .

var request = require('superagent');
var agent1 = request.agent();
agent1.post('url/fileUpload')
      .attach('file',__dirname + "/test.png")
      .end(function(err, res) {
          if (err) {
              console.log(err)
           }
       });
3
Miroslaw Dylag

Essayez le module de demande. Cela fonctionne comme toute autre demande de publication normale

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