在Node.js中使用POST请求上传文件

时间:2014-08-16 23:15:14

标签: node.js multipartform-data http-post

我在Node.js中使用POST请求上传文件时遇到问题。我必须使用request模块来完成它(没有外部的npms)。服务器需要使用包含文件数据的file字段进行多部分请求。在没有使用任何外部模块的情况下,在Node.js中做起来似乎很容易。

我尝试使用this example但未成功:

request.post({
  uri: url,
  method: 'POST',
  multipart: [{
    body: '<FILE_DATA>'
  }]
}, function (err, resp, body) {
  if (err) {
    console.log('Error!');
  } else {
    console.log('URL: ' + body);
  }
});

5 个答案:

答案 0 :(得分:89)

看起来您已经在使用request module

在这种情况下,您需要发布multipart/form-data即可使用其form feature

var req = request.post(url, function (err, resp, body) {
  if (err) {
    console.log('Error!');
  } else {
    console.log('URL: ' + body);
  }
});
var form = req.form();
form.append('file', '<FILE_DATA>', {
  filename: 'myfile.txt',
  contentType: 'text/plain'
});

但如果您想从文件系统发布一些现有文件,那么您可以将其作为可读流传递:

form.append('file', fs.createReadStream(filepath));

request将自行提取所有相关元数据。

有关发布multipart/form-data的详细信息,请参阅request内部使用的node-form-data module

答案 1 :(得分:17)

formData实现的request字段的未记录功能是将选项传递给它使用的form-data模块的能力:

request({
  url: 'http://example.com',
  method: 'POST',
  formData: {
    'regularField': 'someValue',
    'regularFile': someFileStream,
    'customBufferFile': {
      value: fileBufferData,
      options: {
        filename: 'myfile.bin'
      }
    }
  }
}, handleResponse);

如果您需要避免调用requestObj.form()但需要将缓冲区上传为文件,这将非常有用。 form-data模块还接受contentType(MIME类型)和knownLength选项。

This change于2014年10月被添加(因此在询问此问题后2个月),因此现在可以安全使用(2017年以上)。这相当于v2.46.0的版本request或更高版本。

答案 2 :(得分:4)

Leonid Beschastny的答案有效,但我还必须将ArrayBuffer转换为Node request模块中使用的Buffer。在将文件上传到服务器之后,我使用了与HTML5 FileAPI相同的格式(我使用Meteor)。下面的完整代码 - 也许对其他人有帮助。

function toBuffer(ab) {
  var buffer = new Buffer(ab.byteLength);
  var view = new Uint8Array(ab);
  for (var i = 0; i < buffer.length; ++i) {
    buffer[i] = view[i];
  }
  return buffer;
}

var req = request.post(url, function (err, resp, body) {
  if (err) {
    console.log('Error!');
  } else {
    console.log('URL: ' + body);
  }
});
var form = req.form();
form.append('file', toBuffer(file.data), {
  filename: file.name,
  contentType: file.type
});

答案 3 :(得分:4)

您还可以使用&#34;自定义选项&#34;来自请求库的支持。此格式允许您创建多部分表单上载,但具有文件和额外表单信息的组合条目,如文件名或内容类型。我发现有些库希望使用这种格式接收文件上传,特别是像multer这样的库。

此方法已正式记录在请求文档的表单部分 - https://github.com/request/request#forms

//toUpload is the name of the input file: <input type="file" name="toUpload">

let fileToUpload = req.file;

let formData = {
    toUpload: {
      value: fs.createReadStream(path.join(__dirname, '..', '..','upload', fileToUpload.filename)),
      options: {
        filename: fileToUpload.originalname,
        contentType: fileToUpload.mimeType
      }
    }
  };
let options = {
    url: url,
    method: 'POST',
    formData: formData
  }
request(options, function (err, resp, body) {
    if (err)
      cb(err);

    if (!err && resp.statusCode == 200) {
      cb(null, body);
    }
  });

答案 4 :(得分:0)

 const remoteReq = request({
    method: 'POST',
    uri: 'http://host.com/api/upload',
    headers: {
      'Authorization': 'Bearer ' + req.query.token,
      'Content-Type': req.headers['content-type'] || 'multipart/form-data;'
    }
  })
  req.pipe(remoteReq);
  remoteReq.pipe(res);