Comment afficher multipart / form-data avec node.js superagent

j'essaie d'envoyer le type de contenu dans ma requête superagent post à multipart/form-data.

var myagent = superagent.agent();

myagent
  .post('http://localhost/endpoint')
  .set('api_key', apikey)
  .set('Content-Type', 'multipart/form-data')
  .send(fields)
  .end(function(error, response){
    if(error) { 
       console.log("Error: " + error);
    }
  });

L'erreur que j'obtiens est: TypeError: Argument doit être une chaîne de caractères

Si je retire la:

.set('Content-Type', 'multipart/form-data')

Je ne reçois pas d'erreur mais mon arrière-plan reçoit la requête en tant que content-type: application / json

Comment puis-je forcer le type de contenu à être multipart/form-data pour que je puisse accéder à req.les fichiers()?

17
demandé sur treecoder 2012-12-13 21:14:16

5 réponses

Essayer .type('form') plutôt .set('Content-Type', 'multipart/form-data')

http://visionmedia.github.io/superagent/#setting-the-content-type

14
répondu risyasin 2016-07-07 15:06:42

2017, faire de cette façon.

tout d'abord, vous ne mentionnez aucun des éléments suivants:

.set('Content-Type', 'multipart/form-data')

OR

.type('form')

Deuxièmement, vous N'utilisez pas le .send, vous utilisez .field(name, value).

Un exemple

disons que vous vouliez envoyer un formulaire-Demande de données avec ce qui suit:

  • deux champs de texte: name et phone
  • fichier: photo

donc votre demande sera quelque chose comme ceci:

superagent
  .post( 'https://example.com/api/foo.bar' )
  .set('Authorization', '...')
  .accept('application/json')
  .field('name', 'My name')
  .field('phone', 'My phone')
  .attach('photo', 'path/to/photo.gif')

  .then((result) => {
    // process the result here
  })
  .catch((err) => {
    throw err;
  });

et, disons que vous vouliez envoyer JSON comme valeur d'un de vos champs, alors vous le feriez.

superagent
  .post( 'https://example.com/api/dog.crow' )
  .accept('application/json')

  .field('data', JSON.stringify({ name: 'value' })   )

  .then( ... )
  .catch( ... )
13
répondu treecoder 2017-07-11 04:17:10

Il n'est pas clair ce qui est dans le fields variable que vous envoyez, mais voici quelques informations qui peuvent vous aider à déterminer où votre problème.

pour commencer, si vous essayez réellement de construire une requête multi-pièces, voici la documentation officielle pour le faire:http://visionmedia.github.com/superagent/#multipart-requests

pour l'erreur que vous avez obtenu...

La raison en est que, pendant le processus de préparation la demande, SuperAgent vérifie les données à envoyer pour voir si c'est une chaîne. Si ce N'est pas le cas, il tente de sérialiser les données en fonction de la valeur du type de contenu, comme indiqué ci-dessous:

exports.serialize = {
  'application/x-www-form-urlencoded': qs.stringify,
  'application/json': JSON.stringify
};

qui est utilisé ici:

// body
if ('HEAD' != method && !req._headerSent) {
  // serialize stuff
  if ('string' != typeof data) {
    var serialize = exports.serialize[req.getHeader('Content-Type')];
    if (serialize) data = serialize(data);
  }

  // content-length
  if (data && !req.getHeader('Content-Length')) {
    this.set('Content-Length', Buffer.byteLength(data));
  }
}

cela signifie que pour définir un formulaire 'Content-Type' manuellement, vous utiliserez

.set('Content-Type', 'application/x-www-form-urlencoded')

ou

.type('form') risyasin mentionnés

tout autre 'type de contenu' ne sera pas sérialisé, et Buffer.byteLength(data) lancera ensuite le TypeError: Argument must be a string exception si la valeur de votre fields variable n'est pas une chaîne.

7
répondu Chad McElligott 2017-05-23 11:33:14

<input type="file" onchange="handleInputChange()">

import request from 'superagent';

handleInputChange = (event) => {
  console.log(event.target.files[0]);

  let fileObj = event.target.files[0];
  let name = '';
  let ext = '';
  fileObj.name.split('.').map((val, index, arr) => {
    if (index === arr.length - 1) ext += val;
    else name += val;
  });
  let size = fileObj.size;
  let type = fileObj.type;

  let reader = new FileReader();
  reader.readAsDataURL(fileObj);
  reader.onloadend = function(e) {
    request.post('/api/project-image/')
      .set({
        'Accept': 'application/json'
      })
      .send({
        projectName: 'test',
        file: e.target.result.split(',').pop(),
        name: name,
        ext: ext,
        type: type,
        size: size
      })
      .end(function(err, res) {
        if (err) {
          console.log(err);
        } else if (res) {
          const obj = assign({}, event);
          obj.field = props.field;
          obj.src = res.body.filename;
          obj.uid = props.uid;
          ActionCreator.editImage(obj);
          ActionCreator.toggleEditImage(obj);
        }
      });
  };
};
1
répondu SirRodge 2015-10-15 23:01:10

Voici ce qui a fonctionné pour moi. J'avais un seul formulaire de champ, qui téléchargeait un fichier. J'ai transformé le formulaire en un élément FormData HTML5 et je l'ai fait comme suit:

var frm = new FormData(document.getElementById('formId'));
var url =  'url/here';

superagent.post(url)                    
.attach('fieldInFormName', frm.get('fieldInFormName'))                                        
.end( function (error, response) {
    //handle response
});

s'il vous plaît noter, j'ai essayé diverses façons de définir le 'Content-Type' manuellement dans superagent, et il n'a jamais fonctionné correctement en raison de l'identificateur multipart nécessaire dans le Content-Type.

-1
répondu Burneh 2016-08-29 17:26:36