在 Node.js 中使用 POST 请求上传文件
Posted
技术标签:
【中文标题】在 Node.js 中使用 POST 请求上传文件【英文标题】:Uploading file using POST request in Node.js 【发布时间】:2014-10-10 06:41:31 【问题描述】:我时遇到问题。我必须使用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);
);
【问题讨论】:
你的表格有enctype="multipart/form-data"
选项吗?
我没有使用任何形式。是服务器请求。我正在使用套接字将文件从浏览器发送到服务器,然后我必须使用 POST 请求将该文件发送到另一台服务器。
【参考方案1】:
看起来您已经在使用request
module。
在这种情况下,您只需使用form
feature 发布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
的更多信息,请参阅node-form-data
module,request
在内部使用。
【讨论】:
在学习node和request模块的时候,我很困惑为什么在调用post
方法后可以修改表单。埋在request 文档中的是解释 - 形式“可以修改,直到在事件循环的下一个周期触发请求”。
我在使用 form 和 form.append 时不断收到“[Error: write after end]”,有人知道为什么吗?
@VitorFreitas 你应该调用req.form()
并在调用request.post
后立即用所有适当的数据同步填充它。在同一个事件循环滴答期间执行此操作很重要,否则您的请求可能已经发送并且底层流关闭。
request 已弃用,您有替代方案吗?
@David got 是一个不错的选择【参考方案2】:
request
实现的 formData
字段的一个未记录功能是能够将选项传递给它使用的 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 年+)。这相当于request
的v2.46.0
或更高版本。
【讨论】:
【参考方案3】: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
);
【讨论】:
有一种更简单的方法可以将ArrayBuffer
转换为Buffer
,使用内置的Buffer
constructor from an array of octets:var buffer = new Buffer(new Uint8Array(ab));
你上一个函数中file.data、file.name和file.type中的“文件”是从哪里来的?我没有在其他任何地方看到该变量。
我正在使用 Meteor 和社区包进行文件管理。但是,如果您使用的是纯节点,那么您可以使用文件系统函数来获取有关文件及其数据的所有信息nodejs.org/api/fs.html【参考方案4】:
您还可以使用请求库中的“自定义选项”支持。此格式允许您创建多部分表单上传,但包含文件和额外表单信息(如文件名或内容类型)的组合条目。我发现一些库希望接收使用这种格式的文件上传,特别是像 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);
);
【讨论】:
请edit 回答您的问题,并添加一些关于您的代码如何工作的解释或评论。这将帮助其他用户确定您的答案是否足够有趣以供考虑。否则人们必须分析你的代码(这需要时间),甚至模糊地知道这是否是他们需要的。谢谢! 5 年后有人会想要一个解释,而你不会在身边或不会打扰。这就是为什么 Fabio 要求您在回复中而不是应要求提供解释。【参考方案5】:我是这样做的:
// Open file as a readable stream
const fileStream = fs.createReadStream('./my-file.ext');
const form = new FormData();
// Pass file stream directly to form
form.append('my file', fileStream, 'my-file.ext');
【讨论】:
【参考方案6】: 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);
【讨论】:
以上是关于在 Node.js 中使用 POST 请求上传文件的主要内容,如果未能解决你的问题,请参考以下文章
Node js HTTP 服务器/静态 Servlet POST 请求
从 Electron 应用程序发出多部分 POST 请求以进行文件上传