26

我正在尝试将我的超级代理发布请求中的内容类型发送到 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: Argument must be a string

如果我删除:

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

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

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

4

4 回答 4

33

首先,您没有提及以下任何一项:

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

或者

.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 作为您的某个字段的值发送,那么您将执行此操作。

try {
  await superagent
         .post( 'https://example.com/api/dog.crow' )
         .accept('application/json')
         .field('data', JSON.stringify({ name: 'value' }))
}
catch ( ex ) {
    // .catch() stuff
}

// .then() stuff...
于 2017-05-03T06:01:54.430 回答
16

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

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

于 2013-03-15T12:25:14.453 回答
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提到的

任何其他“Content-Type”都不会被序列化,如果变量的值不是字符串,Buffer.byteLength(data)则会随后引发TypeError: Argument must be a string异常 。fields

于 2013-03-26T04:34:51.000 回答
-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 中需要多部分标识符,它从未正常工作。

于 2016-08-29T17:26:36.170 回答