【问题标题】:How to post multipart/form-data with node.js superagent如何使用 node.js superagent 发布 multipart/form-data
【发布时间】:2020-01-15 08:16:41
【问题描述】:

我正在尝试将我的 superagent 发布请求中的内容类型发送到 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()?

【问题讨论】:

  • 如果您尝试执行docs 中的示例之一会发生什么?尝试不设置内容类型,并按照该部分的最后一个示例重复使用field。这可能不是您最终想要实现的,但它可以帮助调试问题所在。

标签: node.js superagent


【解决方案1】:

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

.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...

【讨论】:

  • 对我来说,在前端,.attach('photo', 'path/to/photo.gif') 不起作用,它给出了一个错误:parameter 2 is not of type 'Blob'。我必须改用文件描述符,然后一切都很好。
【解决方案2】:

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

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

【讨论】:

  • 它不再工作了。我使用 type('form') 获得 MIME 类型 application/x-www-form-urlencoded。与文档一致。
【解决方案3】:

尚不清楚您发送的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));
  }
}

这意味着要手动设置表单“内容类型”,您将使用

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

.type('form')risyasin 一样

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

【讨论】:

    【解决方案4】:

    这对我有用。我有一个单字段表单,即上传文件。我将表单转换为 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 中需要多部分标识符,它从未正常工作。

    【讨论】:

      猜你喜欢
      • 2015-10-31
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 2018-12-26
      • 1970-01-01
      相关资源
      最近更新 更多