如何使用node.js superagent发布multipart / form-data

时间:2012-12-13 17:14:17

标签: node.js superagent

我正在尝试将我的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);
    }
  });

我得到的错误是:     TypeError:参数必须是字符串

如果我删除了:

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

我没有收到任何错误,但我的后端正在接收内容类型的请求:application / json

如何强制内容类型为multipart / form-data以便我可以访问req.files()?

4 个答案:

答案 0 :(得分:20)

2017 中,这样做。

首先,您不要提及以下任何一种情况:

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

OR

.type('form')

其次,您不使用.send,而是使用.field(name, value)

一个例子

我们假设您要发送包含以下内容的表单数据请求:

  • 两个文字字段:namephone
  • 一个文件:photo

所以你的请求将是这样的:

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

而且,让我们假设您想要将JSON作为某个字段的值发送,那么您就是这样做的。

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

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

  .then( ... )
  .catch( ... )

答案 1 :(得分:14)

尝试 .type('form') 代替 .set('Content-Type', 'multipart/form-data')

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

答案 2 :(得分:8)

目前尚不清楚您发送的fields变量中的内容,但这里有一些信息可以帮助您确定问题所在。

首先,如果您实际上是在尝试构建多部分请求,那么这是执行此操作的官方文档:http://visionmedia.github.com/superagent/#multipart-requests

至于你得到的错误......

原因是在准备请求的过程中,SuperAgent会检查要发送的数据以查看它是否为字符串。如果不是,它会尝试根据“Content-Type”的值序列化数据,如下所示:

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

在这里使用:

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

这意味着要手动设置表单'Content-Type',您将使用

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

.type('form')提到risyasin

任何其他“内容类型”都不会被序列化,如果Buffer.byteLength(data)变量的值不是字符串,TypeError: Argument must be a string将随后抛出fields异常。

答案 3 :(得分:-1)

这对我有用。我有一个字段表单,即上传文件。我将表单转换为HTML5 FormData元素,然后执行如下操作:

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

请注意,我尝试了各种方法在superagent中手动设置'Content-Type',但由于Content-Type中需要多部分标识符,因此无法正常工作。