Node JS 通过 HTTP 上传文件流
Node JS upload file streams over HTTP
我正在将我的一个项目从 request
切换到更多 light-weight(例如 got、axios 或 fetch)。一切进展顺利,但是,我在尝试上传文件流时遇到问题(PUT
和 POST
)。它适用于请求包,但其他三个中的任何一个 return 来自服务器的 500。
我知道 500 通常意味着服务器端有问题,但它只与我正在测试的 HTTP 包一致。当我将我的代码恢复为使用 request
时,它工作正常。
这是我当前的请求代码:
Request.put(`http://endpoint.com`, {
headers: {
Authorization: `Bearer ${account.token.access_token}`
},
formData: {
content: fs.createReadStream(localPath)
}
}, (err, response, body) => {
if (err) {
return callback(err);
}
return callback(null, body);
});
这是使用另一个包的尝试之一(在本例中,得到):
got.put(`http://endpoint.com`, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${account.token.access_token}`,
},
body: {
content: fs.createReadStream(localPath)
}
})
.then(response => {
return callback(null, response.body);
})
.catch(err => {
return callback(err);
});
根据 got 文档,我也尝试根据它的示例将 form-data
包与它结合使用,但我仍然遇到同样的问题。
我能收集到的这两个之间的唯一区别是 got
我必须手动指定 Content-Type
header 否则端点确实给我一个正确的错误。否则,我不确定这两个包是如何用流构建 body 的,但正如我所说,fetch
和 axios
也产生与 [=17 完全相同的错误=].
如果您想要使用 fetch
或 axios
的任何片段,我也很乐意 post 它们。
看起来这是一个 headers 问题。如果我直接从 FormData
(即 headers: form.getHeaders()
)使用 headers,然后再添加额外的 headers(Authorization
),那么这最终会起作用就好了。
我知道不久前有人问过这个问题,但我也想念简单的 pipe support from the request package
const request = require('request');
request
.get("https://res.cloudinary.com/demo/image/upload/sample.jpg")
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
并且不得不进行一些试验以从当前库中找到类似的功能。
不幸的是,我没有使用过“got”,但我希望以下 2 个示例可以帮助其他有兴趣使用本机 http/https libraries or the popular axios 库的人
HTTP/HTTPS
支持管道!
const http = require('http');
const https = require('https');
console.log("[i] Test pass-through: http/https");
// Note: http/https must match URL protocol
https.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
(imageStream) => {
console.log(" [i] Received stream");
imageStream.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
);
}
);
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
)
Axios
注意 imageStream.data
的用法,它被附加到 Axios 配置中的 data
。
const axios = require('axios');
(async function selfInvokingFunction() {
console.log("[i] Test pass-through: axios");
const imageStream = await axios.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
{
responseType: "stream", // Important to ensure axios provides stream
}
);
console.log(" [i] Received stream");
const upload = await axios({
method: "post",
url: "http://127.0.0.1:8000/api/upload/stream/",
data: imageStream.data,
headers: {
"Content-Type": imageStream.headers["content-type"],
},
});
console.log("Upload response", upload.data);
})();
对我来说,当我在 FormData 上添加其他参数时才有效。
之前
const form = new FormData();
form.append('file', fileStream);
之后
const form = new FormData();
form.append('file', fileStream, 'my-whatever-file-name.mp4');
这样我就可以将流从我的后端发送到节点中的另一个后端,等待 multipart/form-data 中名为 'file'
的文件
我正在将我的一个项目从 request
切换到更多 light-weight(例如 got、axios 或 fetch)。一切进展顺利,但是,我在尝试上传文件流时遇到问题(PUT
和 POST
)。它适用于请求包,但其他三个中的任何一个 return 来自服务器的 500。
我知道 500 通常意味着服务器端有问题,但它只与我正在测试的 HTTP 包一致。当我将我的代码恢复为使用 request
时,它工作正常。
这是我当前的请求代码:
Request.put(`http://endpoint.com`, {
headers: {
Authorization: `Bearer ${account.token.access_token}`
},
formData: {
content: fs.createReadStream(localPath)
}
}, (err, response, body) => {
if (err) {
return callback(err);
}
return callback(null, body);
});
这是使用另一个包的尝试之一(在本例中,得到):
got.put(`http://endpoint.com`, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${account.token.access_token}`,
},
body: {
content: fs.createReadStream(localPath)
}
})
.then(response => {
return callback(null, response.body);
})
.catch(err => {
return callback(err);
});
根据 got 文档,我也尝试根据它的示例将 form-data
包与它结合使用,但我仍然遇到同样的问题。
我能收集到的这两个之间的唯一区别是 got
我必须手动指定 Content-Type
header 否则端点确实给我一个正确的错误。否则,我不确定这两个包是如何用流构建 body 的,但正如我所说,fetch
和 axios
也产生与 [=17 完全相同的错误=].
如果您想要使用 fetch
或 axios
的任何片段,我也很乐意 post 它们。
看起来这是一个 headers 问题。如果我直接从 FormData
(即 headers: form.getHeaders()
)使用 headers,然后再添加额外的 headers(Authorization
),那么这最终会起作用就好了。
我知道不久前有人问过这个问题,但我也想念简单的 pipe support from the request package
const request = require('request');
request
.get("https://res.cloudinary.com/demo/image/upload/sample.jpg")
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
并且不得不进行一些试验以从当前库中找到类似的功能。
不幸的是,我没有使用过“got”,但我希望以下 2 个示例可以帮助其他有兴趣使用本机 http/https libraries or the popular axios 库的人
HTTP/HTTPS
支持管道!
const http = require('http');
const https = require('https');
console.log("[i] Test pass-through: http/https");
// Note: http/https must match URL protocol
https.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
(imageStream) => {
console.log(" [i] Received stream");
imageStream.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
);
}
);
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
)
Axios
注意 imageStream.data
的用法,它被附加到 Axios 配置中的 data
。
const axios = require('axios');
(async function selfInvokingFunction() {
console.log("[i] Test pass-through: axios");
const imageStream = await axios.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
{
responseType: "stream", // Important to ensure axios provides stream
}
);
console.log(" [i] Received stream");
const upload = await axios({
method: "post",
url: "http://127.0.0.1:8000/api/upload/stream/",
data: imageStream.data,
headers: {
"Content-Type": imageStream.headers["content-type"],
},
});
console.log("Upload response", upload.data);
})();
对我来说,当我在 FormData 上添加其他参数时才有效。
之前
const form = new FormData();
form.append('file', fileStream);
之后
const form = new FormData();
form.append('file', fileStream, 'my-whatever-file-name.mp4');
这样我就可以将流从我的后端发送到节点中的另一个后端,等待 multipart/form-data 中名为 'file'
的文件