Node.js - 为请求创建表单与从 request.post 获取表单之间的区别?
Node.js - difference between creating a form for a request versus getting it from request.post?
今天我添加了将照片上传到 Facebook 到我正在使用的网站的功能。该网站是用 Express node.js 构建的,我正在使用请求 npm 模块上传。
我不断收到错误消息:“(#324) 需要上传文件”。我认为这与我尝试上传的照片文件有关,所以我尝试了将其转换为 base64、更改 headers、手动创建 POST 请求等的不同变体
我最终尝试了一个响应的整个代码,令我惊讶的是,它起作用了,即使图像数据只是来自 fs.createReadStream(req.file.path)
,我之前已经尝试过很多次了。
我发现不同之处在于我将 form-data 添加到我的请求中的方式。最初,我将其定义为内联:
request({
url: 'https://graph.facebook.com/me/photos?access_token=' + req.user.facebook.token,
method: "POST",
form: {
source: fs.createReadStream(req.file.path),
message: req.body.message
}
}, function(error, response, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
});
这一直给我之前提到的错误。我找到的代码看起来有点不同。
serverRequest = request.post('https://graph.facebook.com/me/photos?access_token=' + req.user.facebook.token, function(err, res, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
});
form = serverRequest.form()
// append a normal literal text field ...
form.append('message', req.body.message);
// append a file field by streaming a file from disk ...
form.append('source', fs.createReadStream(req.file.path));
这行得通。所以我决定比较一下这两种不同的形式objects。它们很大,所以我把它们放在 Pastebin 上。第一个可以看到here and the second here。差异很大。
现在我想知道两件事:
- 为什么要创建两个不同的 form-data? creating/appending这两种方法对他们有什么区别?
- 如何将方法 1 中的请求附加到表单? post 请求实际发生在什么时候?我假设它在 request.post(..) 上执行,但是我可以在 form-data 得到 posted.
之前将内容附加到 form-data
编辑:下面回答的问题
mscdex 回答了这个问题。这是我现在用于请求的代码,以防其他人需要它。
request.post(
{
url: 'https://graph.facebook.com/me/photos?access_token=' + authToken,
formData: {
message: message,
source: fs.createReadStream(imageFile.path)
}
}, function(err, res, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
}
);
request
documentation 解释了差异。第一个表单用于提交类型 application/x-www-form-urlencoded
的请求,而第二个表单用于提交类型 multipart/form-data
.
的请求
(二进制)文件通常不能与 application/x-www-form-urlencoded
请求一起提交,因此通常使用 multipart/form-data
代替(尽管某些 Web 服务可能允许您通过 PUT
请求,其中请求的内容是原始文件内容)。
HTTP 请求不会在 request()
时立即发送,因为它是异步的,需要时间进行 DNS 查找、设置用于发出 HTTP 请求的 TCP 连接等。所以在那段时间里,你 可以 向表单附加更多字段(假设 request
不会在事件循环的下一个滴答声之后人为地阻止你这样做),但最好为了安全起见一次性添加它们。
今天我添加了将照片上传到 Facebook 到我正在使用的网站的功能。该网站是用 Express node.js 构建的,我正在使用请求 npm 模块上传。
我不断收到错误消息:“(#324) 需要上传文件”。我认为这与我尝试上传的照片文件有关,所以我尝试了将其转换为 base64、更改 headers、手动创建 POST 请求等的不同变体
我最终尝试了一个响应的整个代码,令我惊讶的是,它起作用了,即使图像数据只是来自 fs.createReadStream(req.file.path)
,我之前已经尝试过很多次了。
我发现不同之处在于我将 form-data 添加到我的请求中的方式。最初,我将其定义为内联:
request({
url: 'https://graph.facebook.com/me/photos?access_token=' + req.user.facebook.token,
method: "POST",
form: {
source: fs.createReadStream(req.file.path),
message: req.body.message
}
}, function(error, response, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
});
这一直给我之前提到的错误。我找到的代码看起来有点不同。
serverRequest = request.post('https://graph.facebook.com/me/photos?access_token=' + req.user.facebook.token, function(err, res, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
});
form = serverRequest.form()
// append a normal literal text field ...
form.append('message', req.body.message);
// append a file field by streaming a file from disk ...
form.append('source', fs.createReadStream(req.file.path));
这行得通。所以我决定比较一下这两种不同的形式objects。它们很大,所以我把它们放在 Pastebin 上。第一个可以看到here and the second here。差异很大。
现在我想知道两件事:
- 为什么要创建两个不同的 form-data? creating/appending这两种方法对他们有什么区别?
- 如何将方法 1 中的请求附加到表单? post 请求实际发生在什么时候?我假设它在 request.post(..) 上执行,但是我可以在 form-data 得到 posted. 之前将内容附加到 form-data
编辑:下面回答的问题 mscdex 回答了这个问题。这是我现在用于请求的代码,以防其他人需要它。
request.post(
{
url: 'https://graph.facebook.com/me/photos?access_token=' + authToken,
formData: {
message: message,
source: fs.createReadStream(imageFile.path)
}
}, function(err, res, body) {
var bodyJSON = JSON.parse(body);
if(bodyJSON.error) {
console.log(bodyJSON.error.message);
}
}
);
request
documentation 解释了差异。第一个表单用于提交类型 application/x-www-form-urlencoded
的请求,而第二个表单用于提交类型 multipart/form-data
.
(二进制)文件通常不能与 application/x-www-form-urlencoded
请求一起提交,因此通常使用 multipart/form-data
代替(尽管某些 Web 服务可能允许您通过 PUT
请求,其中请求的内容是原始文件内容)。
HTTP 请求不会在 request()
时立即发送,因为它是异步的,需要时间进行 DNS 查找、设置用于发出 HTTP 请求的 TCP 连接等。所以在那段时间里,你 可以 向表单附加更多字段(假设 request
不会在事件循环的下一个滴答声之后人为地阻止你这样做),但最好为了安全起见一次性添加它们。