如何使用 multipart/form-data header 和原生 Node.js https.request 上传文件?

How do I upload a file using multipart/form-data header with native Node.js https.request?

我正在尝试使用来自 node.js 的本机 https.request 从我的计算机上传文件。我的代码如下所示:

let query = require('https').request({
  hostname: 'somehost.com',
  path: '/path/to/upload',
  headers: {'Content-Type': 'multipart/form-data'},
  method: 'POST'
}, (res) => {
  let data = '';
  res.on("data", (chunk) => {
    data += chunk.toString('utf8');
  });
  res.on('end', () => {
    console.log("data");
  })
});
query.on("error", (e) => {
  console.error(e);
});
query.write(Buffer[
  {key1: 1, file: require("fs").createReadStream("/path/to/file.txt")}
]);      // I don't know how to put here
query.end();

我没有收到主机的任何响应,文件上传失败。我该怎么做?

上传 multipart/form-data 时,Content-Type header 必须包含一个 boundary, in order to indicate where each "part" lives within the posted data. In order to set the boundary for The Multipart Content-Type, you can use the form-data package from NPM. You could set the header/boundary manually,但 form-data 包会为您处理这件事,让您免于不必担心细节等

为了在您的示例中使用 form-data,您需要执行以下操作:

  1. 新建FormDataobject和append相关部分:

    let formData = new require('form-data')();
    formData.append('key1', 1);
    formData.append('file', require("fs").createReadStream("/path/to/file.txt"));
    
  2. 使用 getHeaders 函数构建正确的 HTTP headers:

    require('https').request({
        headers: formData.getHeaders(),
        // ...
    }
    
  3. 使用pipe允许form-data处理您的数据并将其发送到服务器:

    formData.pipe(query);
    

    进行此更改后,您不再需要调用 query.writequery.end - 调用 pipe 即可完成。

为了完整起见,这是经过我描述的更改后的最终代码:

let formData = new require('form-data')();
formData.append('key1', 1);
formData.append('file', require("fs").createReadStream("/path/to/file.txt"));

let query = require('https').request({
    hostname: 'somehost.com',
    path: '/path/to/upload',
    method: 'POST',
    headers: formData.getHeaders()
}, (res) => {
    let data = '';
    res.on("data", (chunk) => {
        data += chunk.toString('utf8');
    });
    res.on('end', () => {
        console.log(data);
    })
});

query.on("error", (e) => {
    console.error(e);
});

formData.pipe(query);