在 Node.js 中使用 POST 请求上传文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25344879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Uploading file using POST request in Node.js
提问by ?ukasz Jagodziński
I have problem uploading file using POST request in Node.js. I have to use requestmodule to accomplish that (no external npms). Server needs it to be multipart request with the filefield containing file's data. What seems to be easy it's pretty hard to do in Node.js without using any external module.
我在 Node.js 中使用 POST 请求上传文件时遇到问题。我必须使用request模块来完成(没有外部 npms)。服务器需要它是file包含文件数据的字段的多部分请求。在不使用任何外部模块的情况下,在 Node.js 中似乎很容易做到这一点非常困难。
I've tried using this examplebut without success:
我试过使用这个例子但没有成功:
request.post({
uri: url,
method: 'POST',
multipart: [{
body: '<FILE_DATA>'
}]
}, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log('URL: ' + body);
}
});
回答by Leonid Beschastny
Looks like you're already using requestmodule.
看起来您已经在使用requestmodule。
in this case all you need to post multipart/form-datais to use its formfeature:
在这种情况下,您需要发布的multipart/form-data只是使用其form功能:
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'
});
but if you want to post some existing file from your file system, then you may simply pass it as a readable stream:
但是如果你想从你的文件系统中发布一些现有的文件,那么你可以简单地将它作为可读流传递:
form.append('file', fs.createReadStream(filepath));
requestwill extract all related metadata by itself.
request将自行提取所有相关元数据。
For more information on posting multipart/form-datasee node-form-datamodule, which is internally used by request.
有关发布的更多信息,multipart/form-data请参阅node-form-data模块,该模块由request.
回答by Clavin
An undocumented feature of the formDatafield that requestimplements is the ability to pass options to the form-datamodule it uses:
该formData字段的一个未记录功能request是能够将选项传递给form-data它使用的模块:
request({
url: 'http://example.com',
method: 'POST',
formData: {
'regularField': 'someValue',
'regularFile': someFileStream,
'customBufferFile': {
value: fileBufferData,
options: {
filename: 'myfile.bin'
}
}
}
}, handleResponse);
This is useful if you need to avoid calling requestObj.form()but need to upload a buffer as a file. The form-datamodule also accepts contentType(the MIME type) and knownLengthoptions.
如果您需要避免调用requestObj.form()但需要将缓冲区作为文件上传,这将非常有用。该form-data模块还接受contentType(MIME 类型)和knownLength选项。
This changewas added in October 2014 (so 2 months after this question was asked), so it should be safe to use now (in 2017+). This equates to version v2.46.0or above of request.
此更改于 2014 年 10 月添加(因此在提出此问题后 2 个月),因此现在使用应该是安全的(在 2017 年以上)。这相当于版本v2.46.0或以上request。
回答by ?ukasz Jagodziński
Leonid Beschastny's answer works but I also had to convert ArrayBuffer to Buffer that is used in the Node's requestmodule. After uploading file to the server I had it in the same format that comes from the HTML5 FileAPI (I'm using Meteor). Full code below - maybe it will be helpful for others.
Leonid Beschastny 的答案有效,但我还必须将 ArrayBuffer 转换为 Noderequest模块中使用的 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
});
回答by Marwen Landoulsi
You can also use the "custom options" support from the request library. This format allows you to create a multi-part form upload, but with a combined entry for both the file and extra form information, like filename or content-type. I have found that some libraries expect to receive file uploads using this format, specifically libraries like multer.
您还可以使用请求库中的“自定义选项”支持。此格式允许您创建多部分表单上传,但包含文件和额外表单信息(如文件名或内容类型)的组合条目。我发现一些库希望使用这种格式接收文件上传,特别是像 multer 这样的库。
This approach is officially documented in the forms section of the request docs - https://github.com/request/request#forms
这种方法正式记录在请求文档的表单部分 - 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);
}
});

