NodeJS请求如何发送多部分/表单数据POST请求

Pau*_*ing 9 multipartform-data request node.js

我正在尝试将POST请求发送到带有请求中图像的API。我正在使用请求模块执行此操作,但是我尝试执行的所有操作均不起作用。我当前的代码:

const options = {
    method: "POST",
    url: "https://api.LINK.com/file",
    port: 443,
    headers: {
        "Authorization": "Basic " + auth,
        "Content-Type": "multipart/form-data"
    },
    form : {
        "image" : fs.readFileSync("./images/scr1.png")
    }
};

request(options, function (err, res, body) {
    if(err) console.log(err);
    console.log(body);
});
Run Code Online (Sandbox Code Playgroud)

但是Content-Type: application/x-www-form-urlencoded由于某种原因,请求使用...如何解决此问题?

max*_*x_i 9

随着request模块被弃用,请考虑使用form-data(唯一的依赖项;负责处理难看的低级细节(例如计算唯一边界字符串)的小包)和核心http(s)模块。

它有点冗长,但您可以获得较小的生产版本,这总是好的,在无服务器环境中更是如此,因为它可以减少冷启动时间。

// abstract and promisify actual network request
async function makeRequest(formData, options) {
  return new Promise((resolve, reject) => {
    const req = formData.submit(options, (err, res) => {
      if (err) {
        return reject(new Error(err.message))
      }

      if (res.statusCode < 200 || res.statusCode > 299) {
        return reject(new Error(`HTTP status code ${res.statusCode}`))
      }

      const body = []
      res.on('data', (chunk) => body.push(chunk))
      res.on('end', () => {
        const resString = Buffer.concat(body).toString()
        resolve(resString)
      })
    })
  })
}

const formData = new FormData()

formData.append('comment', 'Some note attached to the submitted file')
formData.append('image', fs.createReadStream('./images/logo.png'))

const options = {
  host: 'postman-echo.com',
  path: '/post',
  method: 'POST',
  protocol: 'https:', // note : in the end
  headers: {
    Authorization: `Basic some-token-here`,
  },
}

const res = await makeRequest(formData, options)

Run Code Online (Sandbox Code Playgroud)

更新解决生产/lambda 构建大小。使用该request包的答案会增加3.84mb的占用空间。form-data这里使用的库是304kb


Iva*_*vic 8

文档表格中所述,multipart/form-data请求正在使用form-data库。因此,您需要提供formData选项而不是form选项。

const options = {
    method: "POST",
    url: "https://api.LINK.com/file",
    port: 443,
    headers: {
        "Authorization": "Basic " + auth,
        "Content-Type": "multipart/form-data"
    },
    formData : {
        "image" : fs.createReadStream("./images/scr1.png")
    }
};

request(options, function (err, res, body) {
    if(err) console.log(err);
    console.log(body);
});
Run Code Online (Sandbox Code Playgroud)

  • @JoColina,我解决了这个问题。我使用 **strictSSL: false** 而不是 **port** 属性。然后就可以工作了。 (2认同)

Boo*_*oog 8

恼火的是,几乎所有解决此问题的示例解决方案都包含第三方模块。我知道简单地包含一个模块并复制/粘贴一个代码示例通常更容易,但对于像这样的基本 HTTP 概念来说真的不需要一个。添加模块可以快速增加您在 AWS lambda 等云环境中的占用空间,其中总解决方案文件大小会极大地影响运行时性能。我在这里找到了这个有用的例子,

https://tanaikech.github.io/2017/07/27/multipart-post-request-using-node.js/

var fs = require('fs');
var request = require('request');
var upfile = 'sample.zip';
fs.readFile(upfile, function(err, content){
    if(err){
        console.error(err);
    }
    var metadata = {
        token: "### access token ###",
        channels: "sample",
        filename: "samplefilename",
        title: "sampletitle",
    };
    var url = "https://slack.com/api/files.upload";
    var boundary = "xxxxxxxxxx";
    var data = "";
    for(var i in metadata) {
        if ({}.hasOwnProperty.call(metadata, i)) {
            data += "--" + boundary + "\r\n";
            data += "Content-Disposition: form-data; name=\"" + i + "\"; \r\n\r\n" + metadata[i] + "\r\n";
        }
    };
    data += "--" + boundary + "\r\n";
    data += "Content-Disposition: form-data; name=\"file\"; filename=\"" + upfile + "\"\r\n";
    data += "Content-Type:application/octet-stream\r\n\r\n";
    var payload = Buffer.concat([
            Buffer.from(data, "utf8"),
            new Buffer(content, 'binary'),
            Buffer.from("\r\n--" + boundary + "--\r\n", "utf8"),
    ]);
    var options = {
        method: 'post',
        url: url,
        headers: {"Content-Type": "multipart/form-data; boundary=" + boundary},
        body: payload,
    };
    request(options, function(error, response, body) {
        console.log(body);
    });
});
Run Code Online (Sandbox Code Playgroud)

希望对其他人有帮助!

  • 值得指出的是,这种权衡是难以维护、脆弱的代码。因此,根据您的需求明智地选择您的道路。 (6认同)
  • 您的解决方案使用“请求”模块,其中包括对表单数据的支持。如果您允许的话,它会为您执行此操作,除了您已经包含的依赖项之外,没有新的依赖项。 (2认同)